diff --git a/buildscripts/checkstyle-suppressions.xml b/buildscripts/checkstyle-suppressions.xml
index a579d8189e..1077abc3fa 100644
--- a/buildscripts/checkstyle-suppressions.xml
+++ b/buildscripts/checkstyle-suppressions.xml
@@ -6,4 +6,5 @@
Notes: {{attribute.note | render_markdown}}
{%- endif %}
{%- if attribute.deprecated %}
*
diff --git a/semconv/src/main/java/io/opentelemetry/semconv/resource/attributes/ResourceAttributes.java b/semconv/src/main/java/io/opentelemetry/semconv/resource/attributes/ResourceAttributes.java
index 8400342996..666a2fc5b0 100644
--- a/semconv/src/main/java/io/opentelemetry/semconv/resource/attributes/ResourceAttributes.java
+++ b/semconv/src/main/java/io/opentelemetry/semconv/resource/attributes/ResourceAttributes.java
@@ -25,11 +25,11 @@ public final class ResourceAttributes {
public static final AttributeKey Note: Availability zones are called "zones" on Google Cloud.
+ * Notes:
+ *
+ * Availability zones are called "zones" on Google Cloud.
*/
public static final AttributeKey Note: The prefix of the service SHOULD match the one specified in `cloud.provider`.
+ * Notes:
+ *
+ * The prefix of the service SHOULD match the one specified in Note: Multiple log groups must be supported for cases like multi-container applications,
- * where a single application has sidecar containers, and each write to their own log group.
+ * Notes:
+ *
+ * Multiple log groups must be supported for cases like multi-container applications, where a
+ * single application has sidecar containers, and each write to their own log group.
*/
public static final AttributeKey Note: See the [log group ARN format
- * documentation](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/iam-access-control-overview-cwl.html#CWL_ARN_Format).
+ * Notes:
+ *
+ * See the log
+ * group ARN format documentation.
*/
public static final AttributeKey Note: See the [log stream ARN format
- * documentation](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/iam-access-control-overview-cwl.html#CWL_ARN_Format).
- * One log group can contain several log streams, so these ARNs necessarily identify both a log
- * group and a log stream.
+ * Notes:
+ *
+ * See the log
+ * stream ARN format documentation. One log group can contain several log streams, so these
+ * ARNs necessarily identify both a log group and a log stream.
*/
public static final AttributeKey Note: The device identifier MUST only be defined using the values outlined below. This value
- * is not an advertising identifier and MUST NOT be used as such. On iOS (Swift or Objective-C),
- * this value MUST be equal to the [vendor
- * identifier](https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor).
- * On Android (Java or Kotlin), this value MUST be equal to the Firebase Installation ID or a
- * globally unique UUID which is persisted across sessions in your application. More information
- * can be found [here](https://developer.android.com/training/articles/user-data-ids) on best
- * practices and exact implementation details. Caution should be taken when storing personal data
- * or anything which can identify a user. GDPR and data protection laws may apply, ensure you do
- * your own due diligence.
+ * Notes:
+ *
+ * The device identifier MUST only be defined using the values outlined below. This value is
+ * not an advertising identifier and MUST NOT be used as such. On iOS (Swift or Objective-C), this
+ * value MUST be equal to the vendor
+ * identifier. On Android (Java or Kotlin), this value MUST be equal to the Firebase
+ * Installation ID or a globally unique UUID which is persisted across sessions in your
+ * application. More information can be found here on best practices
+ * and exact implementation details. Caution should be taken when storing personal data or
+ * anything which can identify a user. GDPR and data protection laws may apply, ensure you do your
+ * own due diligence.
*/
public static final AttributeKey Note: It's recommended this value represents a machine readable version of the model
- * identifier rather than the market or consumer-friendly name of the device.
+ * Notes:
+ *
+ * It's recommended this value represents a machine readable version of the model identifier
+ * rather than the market or consumer-friendly name of the device.
*/
public static final AttributeKey Note: It's recommended this value represents a human readable version of the device
- * model rather than a machine readable alternative.
+ * Notes:
+ *
+ * It's recommended this value represents a human readable version of the device model rather
+ * than a machine readable alternative.
*/
public static final AttributeKey Note: This is the name of the function as configured/deployed on the FaaS platform and is
- * usually different from the name of the callback function (which may be stored in the
- * [`code.namespace`/`code.function`](../../trace/semantic_conventions/span-general.md#source-code-attributes)
- * span attributes).
+ * Notes:
+ *
+ * This is the name of the function as configured/deployed on the FaaS platform and is usually
+ * different from the name of the callback function (which may be stored in the Note: Depending on the cloud provider, use:
+ * Notes:
*
- * **AWS Lambda:** The function
- * [ARN](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html). Take care
- * not to use the "invoked ARN" directly but replace any [alias
- * suffix](https://docs.aws.amazon.com/lambda/latest/dg/configuration-aliases.html) with the
- * resolved function version, as the same runtime instance may be invokable with multiple
- * different aliases. **GCP:** The [URI of the
- * resource](https://cloud.google.com/iam/docs/full-resource-names) **Azure:** The [Fully
- * Qualified Resource
- * ID](https://docs.microsoft.com/en-us/rest/api/resources/resources/get-by-id).
+ * Depending on the cloud provider, use:
+ *
+ * Take care not to use the "invoked ARN" directly but replace any alias suffix
+ * with the resolved function version, as the same runtime instance may be invokable with multiple
+ * different aliases.
+ *
+ * On some providers, it may not be possible to determine the full ID at startup, which is why
* this field cannot be made required. For example, on AWS the account ID part of the ARN is not
* available without calling another AWS API which may be deemed too slow for a short-running
- * lambda function. As an alternative, consider setting `faas.id` as a span attribute instead.
+ * lambda function. As an alternative, consider setting Note: Depending on the cloud provider and platform, use:
+ * Notes:
*
- * **AWS Lambda:** The [function
- * version](https://docs.aws.amazon.com/lambda/latest/dg/configuration-versions.html) (an integer
- * represented as a decimal string). **Google Cloud Run:** The
- * [revision](https://cloud.google.com/run/docs/managing/revisions) (i.e., the function name plus
- * the revision suffix). **Google Cloud Functions:** The value of the [`K_REVISION` environment
- * variable](https://cloud.google.com/functions/docs/env-var#runtime_environment_variables_set_automatically).
- * **Azure Functions:** Not applicable. Do not set this attribute.
+ * Depending on the cloud provider and platform, use:
+ *
+ * Note: * **AWS Lambda:** Use the (full) log stream name.
+ * Notes:
+ *
+ * Note: It's recommended to set this attribute since e.g. too little memory can easily
- * stop a Java AWS Lambda function from working correctly. On AWS Lambda, the environment variable
- * `AWS_LAMBDA_FUNCTION_MEMORY_SIZE` provides this information.
+ * Notes:
+ *
+ * It's recommended to set this attribute since e.g. too little memory can easily stop a Java
+ * AWS Lambda function from working correctly. On AWS Lambda, the environment variable Note: MUST be the same for all instances of horizontally scaled services. If the value was
- * not specified, SDKs MUST fallback to `unknown_service:` concatenated with
- * [`process.executable.name`](process.md#process), e.g. `unknown_service:bash`. If
- * `process.executable.name` is not available, the value MUST be set to `unknown_service`.
+ * Notes:
+ *
+ * MUST be the same for all instances of horizontally scaled services. If the value was not
+ * specified, SDKs MUST fallback to Note: A string value having a meaning that helps to distinguish a group of services, for
- * example the team name that owns a group of services. `service.name` is expected to be unique
- * within the same namespace. If `service.namespace` is not specified in the Resource then
- * `service.name` is expected to be unique for all services that have no explicit namespace
- * defined (so the empty/unspecified namespace is simply one more valid namespace). Zero-length
- * namespace string is assumed equal to unspecified namespace.
+ * Notes:
+ *
+ * A string value having a meaning that helps to distinguish a group of services, for example
+ * the team name that owns a group of services. Note: MUST be unique for each instance of the same `service.namespace,service.name` pair (in
- * other words `service.namespace,service.name,service.instance.id` triplet MUST be globally
- * unique). The ID helps to distinguish instances of the same service that exist at the same time
- * (e.g. instances of a horizontally scaled service). It is preferable for the ID to be persistent
- * and stay the same for the lifetime of the service instance, however it is acceptable that the
- * ID is ephemeral and changes during important lifetime events for the service (e.g. service
- * restarts). If the service has no inherent unique ID that can be used as the value of this
- * attribute it is recommended to generate a random Version 1 or Version 4 RFC 4122 UUID (services
- * aiming for reproducible UUIDs may also use Version 5, see RFC 4122 for more recommendations).
+ * Notes:
+ *
+ * MUST be unique for each instance of the same Note: This may be different from `faas.id` if an alias is involved.
+ * Notes:
+ *
+ * This may be different from Note: In some SQL databases, the database name to be used is called "schema name".
+ * Notes:
+ *
+ * In some SQL databases, the database name to be used is called "schema name".
*/
public static final AttributeKey Note: The value may be sanitized to exclude sensitive information.
+ * Notes:
+ *
+ * The value may be sanitized to exclude sensitive information.
*/
public static final AttributeKey Note: When setting this to an SQL keyword, it is not recommended to attempt any client-side
- * parsing of `db.statement` just to get this property, but it should be set if the operation name
- * is provided by the library being instrumented. If the SQL statement has an ambiguous operation,
- * or performs more than one operation, this value may be omitted.
+ * Notes:
+ *
+ * When setting this to an SQL keyword, it is not recommended to attempt any client-side
+ * parsing of Note: If setting a `db.mssql.instance_name`, `net.peer.port` is no longer required (but
- * still recommended if non-standard).
+ * Notes:
+ *
+ * If setting a Note: This mirrors the db.sql.table attribute but references cassandra rather than sql. It
- * is not recommended to attempt any client-side parsing of `db.statement` just to get this
+ * Notes:
+ *
+ * This mirrors the db.sql.table attribute but references cassandra rather than sql. It is not
+ * recommended to attempt any client-side parsing of Note: It is not recommended to attempt any client-side parsing of `db.statement` just to get
- * this property, but it should be set if it is provided by the library being instrumented. If the
- * operation is acting upon an anonymous table, or more than one table, this value MUST NOT be
- * set.
+ * Notes:
+ *
+ * It is not recommended to attempt any client-side parsing of Note: An exception is considered to have escaped (or left) the scope of a span, if that span
- * is ended while the exception is still logically "in flight". This may be actually
- * "in flight" in some languages (e.g. if the exception is passed to a Context
- * manager's `__exit__` method in Python) but will usually be caught at the point of recording
+ * Notes:
+ *
+ * An exception is considered to have escaped (or left) the scope of a span, if that span is
+ * ended while the exception is still logically "in flight". This may be actually
+ * "in flight" in some languages (e.g. if the exception is passed to a Context manager's
+ * It is usually not possible to determine at the point where an exception is thrown whether it
* will escape the scope of a span. However, it is trivial to know that an exception will escape,
- * if one checks for an active exception just before ending the span, as done in the [example
- * above](#exception-end-example).
+ * if one checks for an active exception just before ending the span, as done in the example above.
*
- * It follows that an exception may still escape the scope of the span even if the
- * `exception.escaped` attribute was not set or set to false, since the event might have been
+ * It follows that an exception may still escape the scope of the span even if the Note: SHOULD be equal to the `faas.name` resource attribute of the invoked function.
+ * Notes:
+ *
+ * SHOULD be equal to the Note: SHOULD be equal to the `cloud.provider` resource attribute of the invoked function.
+ * Notes:
+ *
+ * SHOULD be equal to the Note: SHOULD be equal to the `cloud.region` resource attribute of the invoked function.
+ * Notes:
+ *
+ * SHOULD be equal to the Note: `http.url` MUST NOT contain credentials passed via URL in form of
- * `https://username:password@www.example.com/`. In such case the attribute's value should be
- * `https://www.example.com/`.
+ * Notes:
+ *
+ * Note: If `net.transport` is not specified, it can be assumed to be `IP.TCP` except if
- * `http.flavor` is `QUIC`, in which case `IP.UDP` is assumed.
+ * Notes:
+ *
+ * If Note: `http.url` is usually not readily available on the server side but would have to be
- * assembled in a cumbersome and sometimes lossy process from other information (see e.g.
+ * Notes:
+ *
+ * Note: This is not necessarily the same as `net.peer.ip`, which would identify the
+ * Notes:
+ *
+ * This is not necessarily the same as Note: If the key type is not string, it's string representation has to be supplied for
- * the attribute. If the key has no unambiguous, canonical string form, don't include its
- * value.
+ * Notes:
+ *
+ * If the key type is not string, it's string representation has to be supplied for the
+ * attribute. If the key has no unambiguous, canonical string form, don't include its value.
*/
public static final AttributeKey Note: This is the logical name of the service from the RPC interface perspective, which can
- * be different from the name of any implementing class. The `code.namespace` attribute may be
- * used to store the latter (despite the attribute name, it may include a class name; e.g., class
- * with method actually executing the call on the server side, RPC client stub class on the client
- * side).
+ * Notes:
+ *
+ * This is the logical name of the service from the RPC interface perspective, which can be
+ * different from the name of any implementing class. The Note: This is the logical name of the method from the RPC interface perspective, which can
- * be different from the name of any implementing method/function. The `code.function` attribute
- * may be used to store the latter (e.g., method actually executing the call on the server side,
- * RPC client stub method on the client side).
+ * Notes:
+ *
+ * This is the logical name of the method from the RPC interface perspective, which can be
+ * different from the name of any implementing method/function. The cloud.provider.
*/
public static final AttributeKey> AWS_LOG_GROUP_NAMES =
stringArrayKey("aws.log.group.names");
@@ -97,8 +106,11 @@ public final class ResourceAttributes {
/**
* The Amazon Resource Name(s) (ARN) of the AWS log group(s).
*
- *
> AWS_LOG_GROUP_ARNS =
stringArrayKey("aws.log.group.arns");
@@ -110,10 +122,12 @@ public final class ResourceAttributes {
/**
* The ARN(s) of the AWS log stream(s).
*
- *
> AWS_LOG_STREAM_ARNS =
stringArrayKey("aws.log.stream.arns");
@@ -122,9 +136,9 @@ public final class ResourceAttributes {
public static final AttributeKey
+ * code.namespace/code.function span attributes).
*/
public static final AttributeKey
+ *
+ *
+ *
+ *
*
* faas.id as a span attribute
+ * instead.
*/
public static final AttributeKey
+ *
*/
public static final AttributeKeyK_REVISION environment variable.
+ *
+ *
*/
public static final AttributeKey
+ * AWS_LAMBDA_FUNCTION_MEMORY_SIZE provides this information.
*/
public static final AttributeKey
+ * ver or lsb_release -a commands.
*/
public static final AttributeKeyName
+ * in proc/[pid]/status. On Windows, can be set to the base name of
+ * GetProcessImageFileNameW.
*/
public static final AttributeKeyproc/[pid]/exe. On Windows, can be set to the result of
+ * GetProcessImageFileNameW.
*/
public static final AttributeKeyproc/[pid]/cmdline. On Windows, can be set to the
+ * first parameter extracted from GetCommandLineW.
*/
public static final AttributeKeyGetCommandLineW. Do not set this if you
+ * have to assemble it just for monitoring; use process.command_args instead.
*/
public static final AttributeKeyproc/[pid]/cmdline. For
+ * libc-based executables, this would be the full argv vector passed to main.
*/
public static final AttributeKey> PROCESS_COMMAND_ARGS =
stringArrayKey("process.command_args");
@@ -408,37 +457,45 @@ public final class ResourceAttributes {
/**
* Logical name of the service.
*
- *
unknown_service: concatenated with process.executable.name, e.g.
+ * unknown_service:bash. If process.executable.name is not available, the
+ * value MUST be set to unknown_service.
*/
public static final AttributeKeyservice.name.
*
- * service.name is expected to be unique
+ * within the same namespace. If service.namespace is not specified in the Resource
+ * then service.name is expected to be unique for all services that have no explicit
+ * namespace defined (so the empty/unspecified namespace is simply one more valid namespace).
+ * Zero-length namespace string is assumed equal to unspecified namespace.
*/
public static final AttributeKeyservice.namespace,service.name
+ * pair (in other words service.namespace,service.name,service.instance.id triplet
+ * MUST be globally unique). The ID helps to distinguish instances of the same service that exist
+ * at the same time (e.g. instances of a horizontally scaled service). It is preferable for the ID
+ * to be persistent and stay the same for the lifetime of the service instance, however it is
+ * acceptable that the ID is ephemeral and changes during important lifetime events for the
+ * service (e.g. service restarts). If the service has no inherent unique ID that can be used as
+ * the value of this attribute it is recommended to generate a random Version 1 or Version 4 RFC
+ * 4122 UUID (services aiming for reproducible UUIDs may also use Version 5, see RFC 4122 for more
+ * recommendations).
*/
public static final AttributeKeyContext passed to the function (
+ * Lambda-Runtime-Invoked-Function-Arn header on the /runtime/invocation/next
+ * applicable).
*
- * faas.id if an alias is involved.
*/
public static final AttributeKeyfindAndModify, or the SQL keyword.
*
- * db.statement just to get this property, but it should be set if the
+ * operation name is provided by the library being instrumented. If the SQL statement has an
+ * ambiguous operation, or performs more than one operation, this value may be omitted.
*/
public static final AttributeKeydb.mssql.instance_name, net.peer.port is no longer
+ * required (but still recommended if non-standard).
*/
public static final AttributeKeydb.name
+ * attribute.
*/
public static final AttributeKeydb.statement just to get this
* property, but it should be set if it is provided by the library being instrumented. If the
* operation is acting upon an anonymous table, or more than one table, this value MUST NOT be
* set.
@@ -123,8 +139,8 @@ public final class SemanticAttributes {
booleanKey("db.cassandra.idempotence");
/**
- * The number of times a query was speculatively executed. Not set or `0` if the query was not
- * executed speculatively.
+ * The number of times a query was speculatively executed. Not set or 0 if the query
+ * was not executed speculatively.
*/
public static final AttributeKeydb.name attribute.
*/
public static final AttributeKeySELECT command, provided as an
+ * integer. To be used instead of the generic db.name attribute.
*/
public static final AttributeKeydb.name. */
public static final AttributeKeydb.statement just
+ * to get this property, but it should be set if it is provided by the library being instrumented.
+ * If the operation is acting upon an anonymous table, or more than one table, this value MUST NOT
+ * be set.
*/
public static final AttributeKey__exit__ method in Python) but will usually be caught at the point of recording
* the exception in most languages.
*
*
+ * exception.escaped attribute was not set or set to false, since the event might have been
* recorded at a time where it was not clear whether the exception will escape.
*/
public static final AttributeKeyfaas.name resource attribute of the invoked function.
*/
public static final AttributeKeycloud.provider resource attribute of the invoked
+ * function.
*/
public static final AttributeKeycloud.region resource attribute of the invoked function.
*/
public static final AttributeKeynet.peer.ip but for the host IP. Useful in case of a multi-IP host. */
public static final AttributeKeynet.peer.port but for the host port. */
public static final AttributeKeyservice.name
+ * of the remote service. SHOULD be equal to the actual service.name resource
+ * attribute of the remote service if any.
*/
public static final AttributeKeycode.function is defined. Usually the
+ * qualified class or module name, such that code.namespace + some separator +
+ * code.function form a unique identifier for the code unit.
*/
public static final AttributeKeycode.filepath best representing the operation. It SHOULD point
+ * within the code unit named in code.function.
*/
public static final AttributeKeyscheme://host[:port]/path?query[#fragment].
+ * Usually the fragment is not transmitted over HTTP, but if it is known, it should be included
+ * nevertheless.
*
- * http.url MUST NOT contain credentials passed via URL in form of
+ * https://username:password@www.example.com/. In such case the attribute's value should be
+ * https://www.example.com/.
*/
public static final AttributeKeynet.transport is not specified, it can be assumed to be IP.TCP
+ * except if http.flavor is QUIC, in which case IP.UDP is
+ * assumed.
*/
public static final AttributeKeynet.host.name
+ * should be used instead).
*
- * http.url is usually not readily available on the server side but would have to
+ * be assembled in a cumbersome and sometimes lossy process from other information (see e.g.
* open-telemetry/opentelemetry-python/pull/148). It is thus preferred to supply the raw data that
* is available.
*/
@@ -447,96 +483,105 @@ public final class SemanticAttributes {
public static final AttributeKeynet.peer.ip, which would identify the
* network-level peer, which may be a proxy.
*/
public static final AttributeKeyRequestItems object field. */
public static final AttributeKey> AWS_DYNAMODB_TABLE_NAMES =
stringArrayKey("aws.dynamodb.table_names");
- /** The JSON-serialized value of each item in the `ConsumedCapacity` response field. */
+ /** The JSON-serialized value of each item in the
ConsumedCapacity response field. */
public static final AttributeKey> AWS_DYNAMODB_CONSUMED_CAPACITY =
stringArrayKey("aws.dynamodb.consumed_capacity");
- /** The JSON-serialized value of the `ItemCollectionMetrics` response field. */
+ /** The JSON-serialized value of the
ItemCollectionMetrics response field. */
public static final AttributeKeyProvisionedThroughput.ReadCapacityUnits request parameter. */
public static final AttributeKeyProvisionedThroughput.WriteCapacityUnits request parameter. */
public static final AttributeKeyConsistentRead request parameter. */
public static final AttributeKeyProjectionExpression request parameter. */
public static final AttributeKeyLimit request parameter. */
public static final AttributeKeyAttributesToGet request parameter. */
public static final AttributeKey> AWS_DYNAMODB_ATTRIBUTES_TO_GET =
stringArrayKey("aws.dynamodb.attributes_to_get");
- /** The value of the `IndexName` request parameter. */
+ /** The value of the
IndexName request parameter. */
public static final AttributeKeySelect request parameter. */
public static final AttributeKeyGlobalSecondaryIndexes request field
+ */
public static final AttributeKey> AWS_DYNAMODB_GLOBAL_SECONDARY_INDEXES =
stringArrayKey("aws.dynamodb.global_secondary_indexes");
- /** The JSON-serialized value of each item of the `LocalSecondaryIndexes` request field. */
+ /**
+ * The JSON-serialized value of each item of the
LocalSecondaryIndexes request field.
+ */
public static final AttributeKey> AWS_DYNAMODB_LOCAL_SECONDARY_INDEXES =
stringArrayKey("aws.dynamodb.local_secondary_indexes");
- /** The value of the `ExclusiveStartTableName` request parameter. */
+ /** The value of the
ExclusiveStartTableName request parameter. */
public static final AttributeKeyTableNames response parameter. */
public static final AttributeKeyScanIndexForward request parameter. */
public static final AttributeKeySegment request parameter. */
public static final AttributeKeyTotalSegments request parameter. */
public static final AttributeKeyCount response parameter. */
public static final AttributeKeyScannedCount response parameter. */
public static final AttributeKeyAttributeDefinitions request field.
+ */
public static final AttributeKey> AWS_DYNAMODB_ATTRIBUTE_DEFINITIONS =
stringArrayKey("aws.dynamodb.attribute_definitions");
/**
- * The JSON-serialized value of each item in the the `GlobalSecondaryIndexUpdates` request field.
+ * The JSON-serialized value of each item in the the
GlobalSecondaryIndexUpdates
+ * request field.
*/
public static final AttributeKey> AWS_DYNAMODB_GLOBAL_SECONDARY_INDEX_UPDATES =
stringArrayKey("aws.dynamodb.global_secondary_index_updates");
@@ -551,7 +596,7 @@ public final class SemanticAttributes {
public static final AttributeKey
messaging.message_id in that they're not unique.
+ * If the key is null, the attribute MUST NOT be set.
*
- * code.namespace attribute
+ * may be used to store the latter (despite the attribute name, it may include a class name; e.g.,
+ * class with method actually executing the call on the server side, RPC client stub class on the
+ * client side).
*/
public static final AttributeKeycode.function
+ * attribute may be used to store the latter (e.g., method actually executing the call on the
+ * server side, RPC client stub method on the client side).
*/
public static final AttributeKeyjsonrpc property of request/response. Since JSON-RPC 1.0
+ * does not specify this, the value can be omitted.
*/
public static final AttributeKeyid property of request or response. Since protocol allows id to be int, string,
+ * null or missing (for notifications), value is expected to be cast to string for
+ * simplicity. Use empty string in case of null value. Omit entirely if this is a
+ * notification.
*/
public static final AttributeKeyerror.code property of response if it is an error response. */
public static final AttributeKeyerror.message property of response if it is an error response. */
public static final AttributeKey