Module ldclient_context

Context data type When constructing a context by hand, not using new/1, new/2 or new_from_map, then you must include a kind attribute.

Description

Context data type When constructing a context by hand, not using new/1, new/2 or new_from_map, then you must include a kind attribute.

The kind attribute is used to differentiate between a map representing a ldclient_user and one representing a ldclient_context.

Data Types

attribute_key()

attribute_key() = binary() | key | kind | anonymous | private_attributes | name

Attribute keys must be binary() strings. They should not be empty, and they must not be <<"_meta">>.

attribute_map()

attribute_map() = #{attribute_key() => attribute_value()}

attribute_value()

attribute_value() = binary() | integer() | float() | boolean() | attribute_map() | [attribute_value()]

Attribute values should all be data types which are compatible with JSON and nested JSON collections. The leaf nodes of these values are what are ultimately used when evaluating flags which are dependent on attributes.

context()

context() = single_context() | multi_context()

context_part()

context_part() = #{key := key(), name := binary(), private_attributes => [binary()], anonymous => boolean(), attributes => attribute_map()}

The content of a multi context. Should be the same as a single_context/0 aside from missing 'kind'. A multi context is keyed by the 'kind'.

key()

key() = binary()

Keys may be any non-empty binary() string. <<>> and <<"">> are not valid. Keys must be binaries, and should match those in LaunchDarkly exactly. No casing conversions will be applied <<"my_attribute">> will only match <<"my_attribute">>, it would not match <<"myAttribute">>.

kind_value()

kind_value() = binary()

May only contain ASCII letters, numbers, ., _ or -. <<"my_kind.0-1">> would be valid. <<"my:kind.{0}">> would not, it contains ':' and '{}' which are not allowed. Kinds should be binaries, and should match the context kinds exactly. No casing conversions will be applied <<"my_kind">> will only match <<"my_kind">>, it would not match <<"myKind">>.

multi_context()

multi_context() = #{kind := kind_value(), kind_value() := context_part()}

A context which represents multiple kinds. Each kind having its own key and attributes.

A multi-context must contain kind => <<"multi">> at the root.

  MyMultiContext = #{
    %% Multi-contexts must be of kind <<"multi">>.
    kind => <<"multi">>,
    %% The context is namespaced by its kind. This is an 'org' kind context.
    <<"org">> => #{
      // Each component context has its own key and attributes.
      key => <<"my-org-key">>,
      attributes => #{
          <<"someAttribute">> => <<"my-attribute-value">>,
      }
    },
    <<"user">> => #{
      key => <<"my-user-key">>,
      %% Each component context has its own meta attributes. This will only apply the this
      %% 'user' context.
      private_attributes => [<<"firstName">>]
      attributes => #{
          <<"firstName">> => <<"Bob">>,
          <<"lastName">> => <<"Bobberson">>,
      }
    }
  }.
The above multi-context contains both an 'org' and a 'user'. Each with their own key, attributes, and _meta attributes.

single_context()

single_context() = #{key := key(), name => binary(), kind := kind_value(), private_attributes => [binary()], anonymous => boolean(), attributes => attribute_map()}

A context which represents a single kind.

For a single kind context the 'kind' may not be <<"multi">>.

  MyOrgContext = #{
      kind => <<"org">>,
      key => <<"my-org-key">>,
      attributes => #{
        <<"someAttribute">> => <<"my-attribute-value">>
      }
  }.
The above context would be a single kind context representing an organization. It has a key for that organization, and a single attribute 'someAttribute'.

Function Index

get/3Get an attribute value from the specified context kind by the specified attribute reference.
get_canonical_key/1A string that describes the entire Context based on Kind and Key values.
get_key/2Get the key for the specified context kind.
get_kinds/1Get all the kinds in the specified context.
is_valid/2Verify a context is valid.
new/1Create a new 'user' context with the specified key.
new/2Create a new context with the specified key and kind.
new_from_json/1Parse a map created from the JSON representation of a context into an ldclient_context:context().
new_from_map/1Create a context from a map.
new_from_user/1Create a context from an ldclient_user:user().
new_multi_from/1Create a multi context from several multiple single kind contexts.
set/3Set an attribute value with the specified key in a single kind context.
set/4Set an attribute value in the specified context kind with the specified key.
set_private_attributes/2Set private attributes for a single kind context.
set_private_attributes/3Set private attributes for the specified context kind.

Function Details

get/3

get(ContextKind::kind_value(), AttributeReference::ldclient_attribute_reference:attribute_reference() | binary(), Context::context()) -> attribute_value() | null

Get an attribute value from the specified context kind by the specified attribute reference

If the context is a single kind context, and the ContextKind matches the context's kind, and the context contains the specified attribute, then that value will be provided.

If the context is a multi-context, and it contains the specified context kind, and that context kind contains the specified attribute, then that value will be provided.

If the attribute value does not exist, then the null atom will be returned.

get_canonical_key/1

get_canonical_key(Context::context()) -> binary()

A string that describes the entire Context based on Kind and Key values.

This value is used whenever LaunchDarkly needs a string identifier based on all of the Kind and Key values in the context; the SDK may use this for caching previously seen contexts, for instance.

get_key/2

get_key(ContextKind::kind_value(), Context::context()) -> binary() | null

Get the key for the specified context kind.

If the context is of a single kind, and it does not match the specified context kind, then null will be returned.

If the context is a multi-context, and does not contain the specified kind, then null will be returned.

get_kinds/1

get_kinds(Context::context()) -> [binary()]

Get all the kinds in the specified context. Can be a single or multi context.

The kind in the context may be an atom or a binary, but this will always return them as binaries for use in comparison against strings from LaunchDarkly.

is_valid/2

is_valid(Context::context(), AllowEmptyKey::boolean()) -> boolean()

Verify a context is valid.

This will ensure that the context, or contexts of a multi context, have:

1.) Valid keys. Key must exist, must be a binary, and cannot be empty. An exception is made for contexts created from an ldclient_user:user().

2.) Valid kind. Kind must exist, must be a binary, and must be composed of ASCII letters, numbers, as well as '-', '.', and '_'. A context created from a ldclient_user:user() will have a <<"user">> kind.

3.) All parts of a multi context meet #1 and #2.

Other aspects of the context may be invalid, and evaluation will proceed, but those invalid parts will not impact the evaluation. For example an attribute with an atom() key will not successfully targeted by rules. Some of these issues can be avoided by using the new_from_map function which will convert keys.

Evaluations which are done against an invalid context will return default values with a reason of user_not_specified.

new/1

new(Key::binary()) -> single_context()

Create a new 'user' context with the specified key.

new/2

new(Key::binary(), Kind::kind_value()) -> single_context()

Create a new context with the specified key and kind.

new_from_json/1

new_from_json(JsonMap::map()) -> context() | undefined

Parse a map created from the JSON representation of a context into an ldclient_context:context().

If the map cannot be parsed into a context, then undefined will be returned.

new_from_map/1

new_from_map(MapContext::map()) -> Context::context()

Create a context from a map.

Using this method will help to ensure that all your context keys and values are of supported types. For instance converting all atom() keys into binary() (both for attribute keys and kinds). This can be useful for contexts from a serialized source.

If the map contains a 'kind' attribute, then the resulting context will be of that kind. If the map contains a 'kind' attribute, with the value of <<"multi">>, then a multi context will be created, and each top level field in the map will be a component of that context.

If the input map contains invalid data, such as bad kinds, then the context will still be created. If the context contains invalid data, then evaluations will return default values with a reason of 'user_not_specified'.

The same key should not be provided in the map as both an atom and a binary. For instance:
  #{key => <<"the-key">>, <<"key">> => <<"the-key">>}
Create a context without a kind specified:
  ldclient_context:new_from_map(#{
      key => <<"my-key">>,
      attributes => #{
          nested => #{
              deeper => #{
                  value => <<"my-value">>
              }
          }
      }
  }).
  Produces the context
  #{
      key := <<"my-key">>,
      kind := <<"user">>,
      attributes := #{
          <<"nested">> := #{
              <<"deeper">> := #{
                  <<"value">> := <<"my-value">>
              }
          }
      }
  }.
  No kind was included, so it was defaulted to a <<"user">> kind.
  Notice that all the keys, and nested keys, within attributes have been converted to binaries.
Creating a context with a specified kind.
     ldclient_context:new_from_map(#{<<"key">> => <<"my-key">>, <<"kind">> => <<"the-kind">>}).
  Produces the context
  {key := <<"my-key">>, kind := <<"the-kind">>}.
  Notice here how the built-in keys have been corrected to atoms.
  ldclient_context:new_from_map(#{
      kind => <<"multi">>,
      <<"meal">> => #{
          key => <<"user-key">>,
          <<"name">> => <<"the-name">>, %% Key that will become an atom.
          attributes => #{
              potato => #{ %% Key that will become a binary.
                  <<"bacon">> => true,
                  <<"cheese">> => true
              }
          }
      },
      <<"location">> => #{
          key => <<"location-key">>
      }
  }).
  Produces the context
  #{
     kind := <<"multi">>,
     <<"meal">> := #{
         key := <<"user-key">>,
         name := <<"the-name">>,
         attributes := #{
             <<"potato">> := #{
                 <<"bacon">> := true,
                 <<"cheese">> := true
             }
         }
     },
     <<"location">> := #{
         key := <<"location-key">>
     }
  }

new_from_user/1

new_from_user(User::ldclient_user:user()) -> context()

Create a context from an ldclient_user:user().

This function is primarily intended for use by the SDK. It will be used when calling variation methods with ldclient_user:user(). An ldclient_user:user() is detected by the lack of kind.

Creating contexts directly, using ldclient_context:new/1, ldclient_context:new/2, ldclient_context:new_from_map/1, or creating context(), will avoid this conversion.

The user needs to be a valid ldclient_user:user(). A map can be converted to a user using ldclient_user:new_from_map/1. If the user does not have at least a key, then an empty map is returned and it will not validate. An invalid context will result in default values from variation methods.

new_multi_from/1

new_multi_from(Contexts::[single_context()]) -> multi_context() | single_context()

Create a multi context from several multiple single kind contexts.

  MyMultiContext = ldclient_context:new_multi_from([
      ldclient_context:new(<<"user-key">>), %% This defaults to a <<"user">> kind.
      ldclient_context:new(<<"org-key">>, <<"org">>)]).

Each of the contexts being combined should have unique keys. If more than one context of the same kind is added, then only a single context of the duplicated type will remain.

If new_from_multi is called with a list containing a single context, then the single context will be returned. A multi context should contain more than one kind.

set/3

set(AttributeKey::attribute_key(), AttributeValue::attribute_value(), Context::single_context()) -> single_context()

Set an attribute value with the specified key in a single kind context.

This method cannot be used to set attributes in nested maps.

Any built-in attributes private_attributes, anonymous, key, kind, will be set at the top level of the context. Any attributes that are not built-ins will be set in an 'attributes' map.

Attempting to set 'attributes' will result in an attribute named <<"attributes">>.

set/4

set(ContextKind::kind_value(), AttributeKey::attribute_key(), AttributeValue::attribute_value(), Context::context()) -> multi_context()

Set an attribute value in the specified context kind with the specified key.

If the context is a single kind, then it must be of the kind specified.

If it is a multi context, then specified kind must exist in it.

This method cannot be used to set attributes in nested maps.

set_private_attributes/2

set_private_attributes(AttributeValues::[binary()], Context::single_context()) -> single_context()

Set private attributes for a single kind context.

Designate any number of Context attributes, or properties within them, as private: that is, their values will not be sent to LaunchDarkly.

Each parameter can be a simple attribute name, such as "email". Or, if the first character is a slash, the parameter is interpreted as a slash-delimited path to a property within a JSON object, where the first path component is a Context attribute name and each following component is a nested property name: for example, suppose the attribute "address" had the following value

  	#{<<"street">>: #{<<"line1">>: <<"abc">>, <<"line2">>: <<"def">>}}

Using ["/address/street/line1"] in this case would cause the "line1" property to be marked as private. This syntax deliberately resembles JSON Pointer, but other JSON Pointer features such as array indexing are not supported for Private.

This action only affects analytics events that involve this particular Context. To mark some (or all) Context attributes as private for all users, use the overall configuration for the SDK.

The attributes "kind" and "key", and the meta attributes (like private_attribute_names) cannot be made private.

In this example, firstName is marked as private, but lastName is not:

  Context = #{
      kind => <<"org">>,
      key => <<"my-key">>,
      private_attributes: [<<"firstName">>],
      attributes => #{
          <<"firstName">> => <<"Pierre">>,
          <<"lastName">> => <<"Menard">>
      }
  }.
This is a metadata property, rather than an attribute that can be addressed in evaluations: that is, a rule clause that references the attribute name "private_attributes", will not use this value, but instead will use whatever value (if any) you have set for that name with a method such as set/3 or by including it in the attributes map.

set_private_attributes/3

set_private_attributes(ContextKind::kind_value(), AttributeValues::[binary()], Context::context()) -> context()

Set private attributes for the specified context kind.

Context can either be a single kind context of the specified kind or a multi context containing the kind.


Generated by EDoc