AWS SDK

AWS SDK

rev. 05bb688fced53156d14a86b12259a8bc7949d70c (ignoring whitespace)

Files changed:

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-observability-otel/Cargo.toml

@@ -0,1 +0,32 @@
           1  +
# Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
           2  +
[package]
           3  +
name = "aws-smithy-observability-otel"
           4  +
version = "0.1.0"
           5  +
authors = ["AWS Rust SDK Team <aws-sdk-rust@amazon.com>"]
           6  +
description = "Smithy OpenTelemetry observability implementation."
           7  +
edition = "2021"
           8  +
license = "Apache-2.0"
           9  +
repository = "https://github.com/awslabs/smithy-rs"
          10  +
[package.metadata.docs.rs]
          11  +
all-features = true
          12  +
targets = ["x86_64-unknown-linux-gnu"]
          13  +
cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]
          14  +
rustdoc-args = ["--cfg", "docsrs"]
          15  +
          16  +
[dependencies]
          17  +
value-bag = "1.10.0"
          18  +
async-global-executor = "2.4.1"
          19  +
async-task = "=4.7.1"
          20  +
          21  +
[dependencies.aws-smithy-observability]
          22  +
path = "../aws-smithy-observability"
          23  +
version = "0.1.0"
          24  +
          25  +
[dependencies.opentelemetry]
          26  +
version = "0.26.0"
          27  +
features = ["metrics"]
          28  +
[target."cfg(not(target_arch = \"powerpc\"))".dependencies.opentelemetry_sdk]
          29  +
version = "0.26.0"
          30  +
features = ["metrics", "testing"]
          31  +
[dev-dependencies.tokio]
          32  +
version = "1.23.1"

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-observability-otel/LICENSE

@@ -0,1 +0,175 @@
           1  +
           2  +
                                 Apache License
           3  +
                           Version 2.0, January 2004
           4  +
                        http://www.apache.org/licenses/
           5  +
           6  +
   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
           7  +
           8  +
   1. Definitions.
           9  +
          10  +
      "License" shall mean the terms and conditions for use, reproduction,
          11  +
      and distribution as defined by Sections 1 through 9 of this document.
          12  +
          13  +
      "Licensor" shall mean the copyright owner or entity authorized by
          14  +
      the copyright owner that is granting the License.
          15  +
          16  +
      "Legal Entity" shall mean the union of the acting entity and all
          17  +
      other entities that control, are controlled by, or are under common
          18  +
      control with that entity. For the purposes of this definition,
          19  +
      "control" means (i) the power, direct or indirect, to cause the
          20  +
      direction or management of such entity, whether by contract or
          21  +
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
          22  +
      outstanding shares, or (iii) beneficial ownership of such entity.
          23  +
          24  +
      "You" (or "Your") shall mean an individual or Legal Entity
          25  +
      exercising permissions granted by this License.
          26  +
          27  +
      "Source" form shall mean the preferred form for making modifications,
          28  +
      including but not limited to software source code, documentation
          29  +
      source, and configuration files.
          30  +
          31  +
      "Object" form shall mean any form resulting from mechanical
          32  +
      transformation or translation of a Source form, including but
          33  +
      not limited to compiled object code, generated documentation,
          34  +
      and conversions to other media types.
          35  +
          36  +
      "Work" shall mean the work of authorship, whether in Source or
          37  +
      Object form, made available under the License, as indicated by a
          38  +
      copyright notice that is included in or attached to the work
          39  +
      (an example is provided in the Appendix below).
          40  +
          41  +
      "Derivative Works" shall mean any work, whether in Source or Object
          42  +
      form, that is based on (or derived from) the Work and for which the
          43  +
      editorial revisions, annotations, elaborations, or other modifications
          44  +
      represent, as a whole, an original work of authorship. For the purposes
          45  +
      of this License, Derivative Works shall not include works that remain
          46  +
      separable from, or merely link (or bind by name) to the interfaces of,
          47  +
      the Work and Derivative Works thereof.
          48  +
          49  +
      "Contribution" shall mean any work of authorship, including
          50  +
      the original version of the Work and any modifications or additions
          51  +
      to that Work or Derivative Works thereof, that is intentionally
          52  +
      submitted to Licensor for inclusion in the Work by the copyright owner
          53  +
      or by an individual or Legal Entity authorized to submit on behalf of
          54  +
      the copyright owner. For the purposes of this definition, "submitted"
          55  +
      means any form of electronic, verbal, or written communication sent
          56  +
      to the Licensor or its representatives, including but not limited to
          57  +
      communication on electronic mailing lists, source code control systems,
          58  +
      and issue tracking systems that are managed by, or on behalf of, the
          59  +
      Licensor for the purpose of discussing and improving the Work, but
          60  +
      excluding communication that is conspicuously marked or otherwise
          61  +
      designated in writing by the copyright owner as "Not a Contribution."
          62  +
          63  +
      "Contributor" shall mean Licensor and any individual or Legal Entity
          64  +
      on behalf of whom a Contribution has been received by Licensor and
          65  +
      subsequently incorporated within the Work.
          66  +
          67  +
   2. Grant of Copyright License. Subject to the terms and conditions of
          68  +
      this License, each Contributor hereby grants to You a perpetual,
          69  +
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
          70  +
      copyright license to reproduce, prepare Derivative Works of,
          71  +
      publicly display, publicly perform, sublicense, and distribute the
          72  +
      Work and such Derivative Works in Source or Object form.
          73  +
          74  +
   3. Grant of Patent License. Subject to the terms and conditions of
          75  +
      this License, each Contributor hereby grants to You a perpetual,
          76  +
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
          77  +
      (except as stated in this section) patent license to make, have made,
          78  +
      use, offer to sell, sell, import, and otherwise transfer the Work,
          79  +
      where such license applies only to those patent claims licensable
          80  +
      by such Contributor that are necessarily infringed by their
          81  +
      Contribution(s) alone or by combination of their Contribution(s)
          82  +
      with the Work to which such Contribution(s) was submitted. If You
          83  +
      institute patent litigation against any entity (including a
          84  +
      cross-claim or counterclaim in a lawsuit) alleging that the Work
          85  +
      or a Contribution incorporated within the Work constitutes direct
          86  +
      or contributory patent infringement, then any patent licenses
          87  +
      granted to You under this License for that Work shall terminate
          88  +
      as of the date such litigation is filed.
          89  +
          90  +
   4. Redistribution. You may reproduce and distribute copies of the
          91  +
      Work or Derivative Works thereof in any medium, with or without
          92  +
      modifications, and in Source or Object form, provided that You
          93  +
      meet the following conditions:
          94  +
          95  +
      (a) You must give any other recipients of the Work or
          96  +
          Derivative Works a copy of this License; and
          97  +
          98  +
      (b) You must cause any modified files to carry prominent notices
          99  +
          stating that You changed the files; and
         100  +
         101  +
      (c) You must retain, in the Source form of any Derivative Works
         102  +
          that You distribute, all copyright, patent, trademark, and
         103  +
          attribution notices from the Source form of the Work,
         104  +
          excluding those notices that do not pertain to any part of
         105  +
          the Derivative Works; and
         106  +
         107  +
      (d) If the Work includes a "NOTICE" text file as part of its
         108  +
          distribution, then any Derivative Works that You distribute must
         109  +
          include a readable copy of the attribution notices contained
         110  +
          within such NOTICE file, excluding those notices that do not
         111  +
          pertain to any part of the Derivative Works, in at least one
         112  +
          of the following places: within a NOTICE text file distributed
         113  +
          as part of the Derivative Works; within the Source form or
         114  +
          documentation, if provided along with the Derivative Works; or,
         115  +
          within a display generated by the Derivative Works, if and
         116  +
          wherever such third-party notices normally appear. The contents
         117  +
          of the NOTICE file are for informational purposes only and
         118  +
          do not modify the License. You may add Your own attribution
         119  +
          notices within Derivative Works that You distribute, alongside
         120  +
          or as an addendum to the NOTICE text from the Work, provided
         121  +
          that such additional attribution notices cannot be construed
         122  +
          as modifying the License.
         123  +
         124  +
      You may add Your own copyright statement to Your modifications and
         125  +
      may provide additional or different license terms and conditions
         126  +
      for use, reproduction, or distribution of Your modifications, or
         127  +
      for any such Derivative Works as a whole, provided Your use,
         128  +
      reproduction, and distribution of the Work otherwise complies with
         129  +
      the conditions stated in this License.
         130  +
         131  +
   5. Submission of Contributions. Unless You explicitly state otherwise,
         132  +
      any Contribution intentionally submitted for inclusion in the Work
         133  +
      by You to the Licensor shall be under the terms and conditions of
         134  +
      this License, without any additional terms or conditions.
         135  +
      Notwithstanding the above, nothing herein shall supersede or modify
         136  +
      the terms of any separate license agreement you may have executed
         137  +
      with Licensor regarding such Contributions.
         138  +
         139  +
   6. Trademarks. This License does not grant permission to use the trade
         140  +
      names, trademarks, service marks, or product names of the Licensor,
         141  +
      except as required for reasonable and customary use in describing the
         142  +
      origin of the Work and reproducing the content of the NOTICE file.
         143  +
         144  +
   7. Disclaimer of Warranty. Unless required by applicable law or
         145  +
      agreed to in writing, Licensor provides the Work (and each
         146  +
      Contributor provides its Contributions) on an "AS IS" BASIS,
         147  +
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
         148  +
      implied, including, without limitation, any warranties or conditions
         149  +
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
         150  +
      PARTICULAR PURPOSE. You are solely responsible for determining the
         151  +
      appropriateness of using or redistributing the Work and assume any
         152  +
      risks associated with Your exercise of permissions under this License.
         153  +
         154  +
   8. Limitation of Liability. In no event and under no legal theory,
         155  +
      whether in tort (including negligence), contract, or otherwise,
         156  +
      unless required by applicable law (such as deliberate and grossly
         157  +
      negligent acts) or agreed to in writing, shall any Contributor be
         158  +
      liable to You for damages, including any direct, indirect, special,
         159  +
      incidental, or consequential damages of any character arising as a
         160  +
      result of this License or out of the use or inability to use the
         161  +
      Work (including but not limited to damages for loss of goodwill,
         162  +
      work stoppage, computer failure or malfunction, or any and all
         163  +
      other commercial damages or losses), even if such Contributor
         164  +
      has been advised of the possibility of such damages.
         165  +
         166  +
   9. Accepting Warranty or Additional Liability. While redistributing
         167  +
      the Work or Derivative Works thereof, You may choose to offer,
         168  +
      and charge a fee for, acceptance of support, warranty, indemnity,
         169  +
      or other liability obligations and/or rights consistent with this
         170  +
      License. However, in accepting such obligations, You may act only
         171  +
      on Your own behalf and on Your sole responsibility, not on behalf
         172  +
      of any other Contributor, and only if You agree to indemnify,
         173  +
      defend, and hold each Contributor harmless for any liability
         174  +
      incurred by, or claims asserted against, such Contributor by reason
         175  +
      of your accepting any such warranty or additional liability.

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-observability-otel/README.md

@@ -0,1 +0,7 @@
           1  +
# aws-smithy-observability-otel
           2  +
           3  +
This crate contains OpenTelemetry based implementations of the metrics traits from the `aws-smithy-observability` crate.
           4  +
           5  +
<!-- anchor_start:footer -->
           6  +
This crate is part of the [AWS SDK for Rust](https://awslabs.github.io/aws-sdk-rust/) and the [smithy-rs](https://github.com/smithy-lang/smithy-rs) code generator. In most cases, it should not be used directly.
           7  +
<!-- anchor_end:footer -->

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-observability-otel/external-types.toml

@@ -0,1 +0,11 @@
           1  +
allowed_external_types = [
           2  +
    "aws_smithy_observability::error::ObservabilityError",
           3  +
    "aws_smithy_observability::meter::AsyncMeasure",
           4  +
    "aws_smithy_observability::meter::Histogram",
           5  +
    "aws_smithy_observability::meter::Meter",
           6  +
    "aws_smithy_observability::meter::MonotonicCounter",
           7  +
    "aws_smithy_observability::meter::ProvideMeter",
           8  +
    "aws_smithy_observability::meter::UpDownCounter",
           9  +
    "aws_smithy_observability::provider::TelemetryProvider",
          10  +
    "opentelemetry_sdk::metrics::meter_provider::SdkMeterProvider",
          11  +
]

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-observability-otel/src/attributes.rs

@@ -0,1 +0,138 @@
           1  +
/*
           2  +
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           3  +
 * SPDX-License-Identifier: Apache-2.0
           4  +
 */
           5  +
           6  +
//! Utilities to transform back and forth from Smithy Observability [Attributes] to
           7  +
//! OTel [KeyValue]s.
           8  +
           9  +
use std::ops::Deref;
          10  +
          11  +
use aws_smithy_observability::attributes::{AttributeValue, Attributes};
          12  +
use opentelemetry::{KeyValue, Value};
          13  +
          14  +
pub(crate) struct AttributesWrap(Attributes);
          15  +
impl AttributesWrap {
          16  +
    pub(crate) fn new(inner: Attributes) -> Self {
          17  +
        Self(inner)
          18  +
    }
          19  +
}
          20  +
impl Deref for AttributesWrap {
          21  +
    type Target = Attributes;
          22  +
          23  +
    fn deref(&self) -> &Self::Target {
          24  +
        &self.0
          25  +
    }
          26  +
}
          27  +
          28  +
pub(crate) fn kv_from_option_attr(input: Option<&Attributes>) -> Vec<KeyValue> {
          29  +
    input
          30  +
        .map(|attr| AttributesWrap::new(attr.clone()))
          31  +
        .unwrap_or(AttributesWrap::new(Attributes::new()))
          32  +
        .into()
          33  +
}
          34  +
          35  +
#[allow(dead_code)]
          36  +
pub(crate) fn option_attr_from_kv(input: &[KeyValue]) -> Option<Attributes> {
          37  +
    if input.is_empty() {
          38  +
        return None;
          39  +
    }
          40  +
          41  +
    Some(AttributesWrap::from(input).0)
          42  +
}
          43  +
          44  +
impl From<AttributesWrap> for Vec<KeyValue> {
          45  +
    fn from(value: AttributesWrap) -> Self {
          46  +
        value
          47  +
            .0
          48  +
            .into_attributes()
          49  +
            .map(|(k, v)| {
          50  +
                KeyValue::new(
          51  +
                    k,
          52  +
                    match v {
          53  +
                        AttributeValue::I64(val) => Value::I64(val),
          54  +
                        AttributeValue::F64(val) => Value::F64(val),
          55  +
                        AttributeValue::String(val) => Value::String(val.into()),
          56  +
                        AttributeValue::Bool(val) => Value::Bool(val),
          57  +
                        _ => Value::String("UNSUPPORTED ATTRIBUTE VALUE TYPE".into()),
          58  +
                    },
          59  +
                )
          60  +
            })
          61  +
            .collect::<Vec<KeyValue>>()
          62  +
    }
          63  +
}
          64  +
          65  +
impl From<&[KeyValue]> for AttributesWrap {
          66  +
    fn from(value: &[KeyValue]) -> Self {
          67  +
        let mut attrs = Attributes::new();
          68  +
          69  +
        value.iter().for_each(|kv| {
          70  +
            attrs.set(
          71  +
                kv.key.clone(),
          72  +
                match &kv.value {
          73  +
                    Value::Bool(val) => AttributeValue::Bool(*val),
          74  +
                    Value::I64(val) => AttributeValue::I64(*val),
          75  +
                    Value::F64(val) => AttributeValue::F64(*val),
          76  +
                    Value::String(val) => AttributeValue::String(val.clone().into()),
          77  +
                    Value::Array(_) => {
          78  +
                        AttributeValue::String("UNSUPPORTED ATTRIBUTE VALUE TYPE".into())
          79  +
                    }
          80  +
                },
          81  +
            )
          82  +
        });
          83  +
          84  +
        AttributesWrap(attrs)
          85  +
    }
          86  +
}
          87  +
          88  +
#[cfg(test)]
          89  +
mod tests {
          90  +
    use std::collections::HashMap;
          91  +
          92  +
    use super::*;
          93  +
    use aws_smithy_observability::attributes::{AttributeValue, Attributes};
          94  +
    use opentelemetry::Value;
          95  +
          96  +
    #[test]
          97  +
    fn attr_to_kv() {
          98  +
        let mut attrs = Attributes::new();
          99  +
        attrs.set("I64", AttributeValue::I64(64));
         100  +
        attrs.set("F64", AttributeValue::F64(64.0));
         101  +
        attrs.set("String", AttributeValue::String("I AM A STRING".into()));
         102  +
        attrs.set("Bool", AttributeValue::Bool(true));
         103  +
         104  +
        let kv = kv_from_option_attr(Some(&attrs));
         105  +
         106  +
        let kv_map: HashMap<String, Value> = kv
         107  +
            .into_iter()
         108  +
            .map(|kv| (kv.key.to_string(), kv.value))
         109  +
            .collect();
         110  +
         111  +
        assert_eq!(kv_map.get("I64").unwrap(), &Value::I64(64));
         112  +
        assert_eq!(kv_map.get("F64").unwrap(), &Value::F64(64.0));
         113  +
        assert_eq!(
         114  +
            kv_map.get("String").unwrap(),
         115  +
            &Value::String("I AM A STRING".into())
         116  +
        );
         117  +
        assert_eq!(kv_map.get("Bool").unwrap(), &Value::Bool(true));
         118  +
    }
         119  +
         120  +
    #[test]
         121  +
    fn kv_to_attr() {
         122  +
        let kvs: Vec<KeyValue> = vec![
         123  +
            KeyValue::new("Bool", Value::Bool(true)),
         124  +
            KeyValue::new("String", Value::String("I AM A STRING".into())),
         125  +
            KeyValue::new("I64", Value::I64(64)),
         126  +
            KeyValue::new("F64", Value::F64(64.0)),
         127  +
        ];
         128  +
         129  +
        let attrs = option_attr_from_kv(&kvs).unwrap();
         130  +
        assert_eq!(attrs.get("Bool").unwrap(), &AttributeValue::Bool(true));
         131  +
        assert_eq!(
         132  +
            attrs.get("String").unwrap(),
         133  +
            &AttributeValue::String("I AM A STRING".into())
         134  +
        );
         135  +
        assert_eq!(attrs.get("I64").unwrap(), &AttributeValue::I64(64));
         136  +
        assert_eq!(attrs.get("F64").unwrap(), &AttributeValue::F64(64.0));
         137  +
    }
         138  +
}

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-observability-otel/src/lib.rs

@@ -0,1 +0,87 @@
           1  +
/*
           2  +
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           3  +
 * SPDX-License-Identifier: Apache-2.0
           4  +
 */
           5  +
           6  +
/* Automatically managed default lints */
           7  +
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
           8  +
/* End of automatically managed default lints */
           9  +
#![warn(
          10  +
    missing_docs,
          11  +
    rustdoc::missing_crate_level_docs,
          12  +
    unreachable_pub,
          13  +
    rust_2018_idioms
          14  +
)]
          15  +
// The `opentelemetry_sdk` crate uses std::sync::atomic::{AtomicI64, AtomicU64} which are not available on powerpc
          16  +
#![cfg(not(target_arch = "powerpc"))]
          17  +
          18  +
//! Smithy Observability OpenTelemetry
          19  +
//TODO(smithyobservability): once we have finalized everything and integrated metrics with our runtime
          20  +
// libraries update this with detailed usage docs and examples
          21  +
          22  +
pub mod attributes;
          23  +
pub mod meter;
          24  +
          25  +
#[cfg(test)]
          26  +
mod tests {
          27  +
          28  +
    use crate::meter::AwsSdkOtelMeterProvider;
          29  +
    use aws_smithy_observability::global::{get_telemetry_provider, set_telemetry_provider};
          30  +
    use aws_smithy_observability::provider::TelemetryProvider;
          31  +
    use opentelemetry_sdk::metrics::{data::Sum, PeriodicReader, SdkMeterProvider};
          32  +
    use opentelemetry_sdk::runtime::Tokio;
          33  +
    use opentelemetry_sdk::testing::metrics::InMemoryMetricsExporter;
          34  +
          35  +
    // Without these tokio settings this test just stalls forever on flushing the metrics pipeline
          36  +
    #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
          37  +
    async fn can_construct_set_and_use_otel_as_global_telemetry_provider() {
          38  +
        // Create the OTel metrics objects
          39  +
        let exporter = InMemoryMetricsExporter::default();
          40  +
        let reader = PeriodicReader::builder(exporter.clone(), Tokio).build();
          41  +
        let otel_mp = SdkMeterProvider::builder().with_reader(reader).build();
          42  +
          43  +
        // Create the SDK metrics types from the OTel objects
          44  +
        let sdk_mp = AwsSdkOtelMeterProvider::new(otel_mp);
          45  +
        let sdk_tp = TelemetryProvider::builder().meter_provider(sdk_mp).build();
          46  +
          47  +
        // Set the global TelemetryProvider and then get it back out
          48  +
        let _ = set_telemetry_provider(sdk_tp);
          49  +
        let global_tp = get_telemetry_provider().unwrap();
          50  +
          51  +
        // Create an instrument and record a value
          52  +
        let global_meter = global_tp
          53  +
            .meter_provider()
          54  +
            .get_meter("TestGlobalMeter", None);
          55  +
          56  +
        let mono_counter =
          57  +
            global_meter.create_monotonic_counter("TestMonoCounter".into(), None, None);
          58  +
        mono_counter.add(4, None, None);
          59  +
          60  +
        // Flush metric pipeline and extract metrics from exporter
          61  +
        global_tp
          62  +
            .meter_provider()
          63  +
            .as_any()
          64  +
            .downcast_ref::<AwsSdkOtelMeterProvider>()
          65  +
            .unwrap()
          66  +
            .shutdown()
          67  +
            .unwrap();
          68  +
        let finished_metrics = exporter.get_finished_metrics().unwrap();
          69  +
          70  +
        let extracted_mono_counter_data = &finished_metrics[0].scope_metrics[0].metrics[0]
          71  +
            .data
          72  +
            .as_any()
          73  +
            .downcast_ref::<Sum<u64>>()
          74  +
            .unwrap()
          75  +
            .data_points[0]
          76  +
            .value;
          77  +
        assert_eq!(extracted_mono_counter_data, &4);
          78  +
          79  +
        // Get the OTel TP out and shut it down
          80  +
        let foo = global_tp
          81  +
            .meter_provider()
          82  +
            .as_any()
          83  +
            .downcast_ref::<AwsSdkOtelMeterProvider>()
          84  +
            .unwrap();
          85  +
        foo.shutdown().unwrap();
          86  +
    }
          87  +
}

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-observability-otel/src/meter.rs

@@ -0,1 +0,523 @@
           1  +
/*
           2  +
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           3  +
 * SPDX-License-Identifier: Apache-2.0
           4  +
 */
           5  +
           6  +
//! OpenTelemetry based implementations of the Smithy Observability Meter traits.
           7  +
           8  +
use std::fmt::Debug;
           9  +
use std::ops::Deref;
          10  +
use std::sync::Arc;
          11  +
          12  +
use crate::attributes::kv_from_option_attr;
          13  +
use aws_smithy_observability::attributes::{Attributes, Context};
          14  +
use aws_smithy_observability::error::{ErrorKind, ObservabilityError};
          15  +
pub use aws_smithy_observability::meter::{
          16  +
    AsyncMeasure, Histogram, Meter, MonotonicCounter, ProvideMeter, UpDownCounter,
          17  +
};
          18  +
pub use aws_smithy_observability::provider::TelemetryProvider;
          19  +
use opentelemetry::metrics::{
          20  +
    AsyncInstrument as OtelAsyncInstrument, Counter as OtelCounter, Histogram as OtelHistogram,
          21  +
    Meter as OtelMeter, MeterProvider as OtelMeterProvider,
          22  +
    ObservableCounter as OtelObservableCounter, ObservableGauge as OtelObservableGauge,
          23  +
    ObservableUpDownCounter as OtelObservableUpDownCounter, UpDownCounter as OtelUpDownCounter,
          24  +
};
          25  +
use opentelemetry_sdk::metrics::SdkMeterProvider as OtelSdkMeterProvider;
          26  +
          27  +
#[derive(Debug)]
          28  +
struct UpDownCounterWrap(OtelUpDownCounter<i64>);
          29  +
impl UpDownCounter for UpDownCounterWrap {
          30  +
    fn add(&self, value: i64, attributes: Option<&Attributes>, _context: Option<&dyn Context>) {
          31  +
        self.0.add(value, &kv_from_option_attr(attributes));
          32  +
    }
          33  +
}
          34  +
          35  +
#[derive(Debug)]
          36  +
struct HistogramWrap(OtelHistogram<f64>);
          37  +
impl Histogram for HistogramWrap {
          38  +
    fn record(&self, value: f64, attributes: Option<&Attributes>, _context: Option<&dyn Context>) {
          39  +
        self.0.record(value, &kv_from_option_attr(attributes));
          40  +
    }
          41  +
}
          42  +
          43  +
#[derive(Debug)]
          44  +
struct MonotonicCounterWrap(OtelCounter<u64>);
          45  +
impl MonotonicCounter for MonotonicCounterWrap {
          46  +
    fn add(&self, value: u64, attributes: Option<&Attributes>, _context: Option<&dyn Context>) {
          47  +
        self.0.add(value, &kv_from_option_attr(attributes));
          48  +
    }
          49  +
}
          50  +
          51  +
#[derive(Debug)]
          52  +
struct GaugeWrap(OtelObservableGauge<f64>);
          53  +
impl AsyncMeasure for GaugeWrap {
          54  +
    type Value = f64;
          55  +
          56  +
    fn record(
          57  +
        &self,
          58  +
        value: Self::Value,
          59  +
        attributes: Option<&Attributes>,
          60  +
        _context: Option<&dyn Context>,
          61  +
    ) {
          62  +
        self.0.observe(value, &kv_from_option_attr(attributes));
          63  +
    }
          64  +
          65  +
    // OTel rust does not currently support unregistering callbacks
          66  +
    // https://github.com/open-telemetry/opentelemetry-rust/issues/2245
          67  +
    fn stop(&self) {}
          68  +
}
          69  +
          70  +
#[derive(Debug)]
          71  +
struct AsyncUpDownCounterWrap(OtelObservableUpDownCounter<i64>);
          72  +
impl AsyncMeasure for AsyncUpDownCounterWrap {
          73  +
    type Value = i64;
          74  +
          75  +
    fn record(
          76  +
        &self,
          77  +
        value: Self::Value,
          78  +
        attributes: Option<&Attributes>,
          79  +
        _context: Option<&dyn Context>,
          80  +
    ) {
          81  +
        self.0.observe(value, &kv_from_option_attr(attributes));
          82  +
    }
          83  +
          84  +
    // OTel rust does not currently support unregistering callbacks
          85  +
    // https://github.com/open-telemetry/opentelemetry-rust/issues/2245
          86  +
    fn stop(&self) {}
          87  +
}
          88  +
          89  +
#[derive(Debug)]
          90  +
struct AsyncMonotonicCounterWrap(OtelObservableCounter<u64>);
          91  +
impl AsyncMeasure for AsyncMonotonicCounterWrap {
          92  +
    type Value = u64;
          93  +
          94  +
    fn record(
          95  +
        &self,
          96  +
        value: Self::Value,
          97  +
        attributes: Option<&Attributes>,
          98  +
        _context: Option<&dyn Context>,
          99  +
    ) {
         100  +
        self.0.observe(value, &kv_from_option_attr(attributes));
         101  +
    }
         102  +
         103  +
    // OTel rust does not currently support unregistering callbacks
         104  +
    // https://github.com/open-telemetry/opentelemetry-rust/issues/2245
         105  +
    fn stop(&self) {}
         106  +
}
         107  +
         108  +
struct AsyncInstrumentWrap<'a, T>(&'a (dyn OtelAsyncInstrument<T> + Send + Sync));
         109  +
impl<T> AsyncMeasure for AsyncInstrumentWrap<'_, T> {
         110  +
    type Value = T;
         111  +
         112  +
    fn record(
         113  +
        &self,
         114  +
        value: Self::Value,
         115  +
        attributes: Option<&Attributes>,
         116  +
        _context: Option<&dyn Context>,
         117  +
    ) {
         118  +
        self.0.observe(value, &kv_from_option_attr(attributes));
         119  +
    }
         120  +
         121  +
    // OTel rust does not currently support unregistering callbacks
         122  +
    // https://github.com/open-telemetry/opentelemetry-rust/issues/2245
         123  +
    fn stop(&self) {}
         124  +
}
         125  +
         126  +
// The OtelAsyncInstrument trait does not have Debug as a supertrait, so we impl a minimal version
         127  +
// for our wrapper struct
         128  +
impl<T> Debug for AsyncInstrumentWrap<'_, T> {
         129  +
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         130  +
        f.debug_tuple("AsyncInstrumentWrap").finish()
         131  +
    }
         132  +
}
         133  +
         134  +
#[derive(Debug)]
         135  +
struct MeterWrap(OtelMeter);
         136  +
impl Deref for MeterWrap {
         137  +
    type Target = OtelMeter;
         138  +
         139  +
    fn deref(&self) -> &Self::Target {
         140  +
        &self.0
         141  +
    }
         142  +
}
         143  +
         144  +
impl Meter for MeterWrap {
         145  +
    fn create_gauge(
         146  +
        &self,
         147  +
        name: String,
         148  +
        callback: Box<dyn Fn(&dyn AsyncMeasure<Value = f64>) + Send + Sync>,
         149  +
        units: Option<String>,
         150  +
        description: Option<String>,
         151  +
    ) -> Arc<dyn AsyncMeasure<Value = f64>> {
         152  +
        let mut builder = self.f64_observable_gauge(name).with_callback(
         153  +
            move |input: &dyn OtelAsyncInstrument<f64>| {
         154  +
                callback(&AsyncInstrumentWrap(input));
         155  +
            },
         156  +
        );
         157  +
         158  +
        if let Some(desc) = description {
         159  +
            builder = builder.with_description(desc);
         160  +
        }
         161  +
         162  +
        if let Some(u) = units {
         163  +
            builder = builder.with_unit(u);
         164  +
        }
         165  +
         166  +
        Arc::new(GaugeWrap(builder.init()))
         167  +
    }
         168  +
         169  +
    fn create_up_down_counter(
         170  +
        &self,
         171  +
        name: String,
         172  +
        units: Option<String>,
         173  +
        description: Option<String>,
         174  +
    ) -> Arc<dyn UpDownCounter> {
         175  +
        let mut builder = self.i64_up_down_counter(name);
         176  +
        if let Some(desc) = description {
         177  +
            builder = builder.with_description(desc);
         178  +
        }
         179  +
         180  +
        if let Some(u) = units {
         181  +
            builder = builder.with_unit(u);
         182  +
        }
         183  +
         184  +
        Arc::new(UpDownCounterWrap(builder.init()))
         185  +
    }
         186  +
         187  +
    fn create_async_up_down_counter(
         188  +
        &self,
         189  +
        name: String,
         190  +
        callback: Box<dyn Fn(&dyn AsyncMeasure<Value = i64>) + Send + Sync>,
         191  +
        units: Option<String>,
         192  +
        description: Option<String>,
         193  +
    ) -> Arc<dyn AsyncMeasure<Value = i64>> {
         194  +
        let mut builder = self.i64_observable_up_down_counter(name).with_callback(
         195  +
            move |input: &dyn OtelAsyncInstrument<i64>| {
         196  +
                callback(&AsyncInstrumentWrap(input));
         197  +
            },
         198  +
        );
         199  +
         200  +
        if let Some(desc) = description {
         201  +
            builder = builder.with_description(desc);
         202  +
        }
         203  +
         204  +
        if let Some(u) = units {
         205  +
            builder = builder.with_unit(u);
         206  +
        }
         207  +
         208  +
        Arc::new(AsyncUpDownCounterWrap(builder.init()))
         209  +
    }
         210  +
         211  +
    fn create_monotonic_counter(
         212  +
        &self,
         213  +
        name: String,
         214  +
        units: Option<String>,
         215  +
        description: Option<String>,
         216  +
    ) -> Arc<dyn MonotonicCounter> {
         217  +
        let mut builder = self.u64_counter(name);
         218  +
        if let Some(desc) = description {
         219  +
            builder = builder.with_description(desc);
         220  +
        }
         221  +
         222  +
        if let Some(u) = units {
         223  +
            builder = builder.with_unit(u);
         224  +
        }
         225  +
         226  +
        Arc::new(MonotonicCounterWrap(builder.init()))
         227  +
    }
         228  +
         229  +
    fn create_async_monotonic_counter(
         230  +
        &self,
         231  +
        name: String,
         232  +
        callback: Box<dyn Fn(&dyn AsyncMeasure<Value = u64>) + Send + Sync>,
         233  +
        units: Option<String>,
         234  +
        description: Option<String>,
         235  +
    ) -> Arc<dyn AsyncMeasure<Value = u64>> {
         236  +
        let mut builder = self.u64_observable_counter(name).with_callback(
         237  +
            move |input: &dyn OtelAsyncInstrument<u64>| {
         238  +
                callback(&AsyncInstrumentWrap(input));
         239  +
            },
         240  +
        );
         241  +
         242  +
        if let Some(desc) = description {
         243  +
            builder = builder.with_description(desc);
         244  +
        }
         245  +
         246  +
        if let Some(u) = units {
         247  +
            builder = builder.with_unit(u);
         248  +
        }
         249  +
         250  +
        Arc::new(AsyncMonotonicCounterWrap(builder.init()))
         251  +
    }
         252  +
         253  +
    fn create_histogram(
         254  +
        &self,
         255  +
        name: String,
         256  +
        units: Option<String>,
         257  +
        description: Option<String>,
         258  +
    ) -> Arc<dyn Histogram> {
         259  +
        let mut builder = self.f64_histogram(name);
         260  +
        if let Some(desc) = description {
         261  +
            builder = builder.with_description(desc);
         262  +
        }
         263  +
         264  +
        if let Some(u) = units {
         265  +
            builder = builder.with_unit(u);
         266  +
        }
         267  +
         268  +
        Arc::new(HistogramWrap(builder.init()))
         269  +
    }
         270  +
}
         271  +
         272  +
/// An OpenTelemetry based implementation of the AWS SDK's [ProvideMeter] trait
         273  +
#[non_exhaustive]
         274  +
#[derive(Debug)]
         275  +
pub struct AwsSdkOtelMeterProvider {
         276  +
    meter_provider: OtelSdkMeterProvider,
         277  +
}
         278  +
         279  +
impl AwsSdkOtelMeterProvider {
         280  +
    /// Create a new [AwsSdkOtelMeterProvider] from an [OtelSdkMeterProvider].
         281  +
    pub fn new(otel_meter_provider: OtelSdkMeterProvider) -> Self {
         282  +
        Self {
         283  +
            meter_provider: otel_meter_provider,
         284  +
        }
         285  +
    }
         286  +
         287  +
    /// Flush the metric pipeline.
         288  +
    pub fn flush(&self) -> Result<(), ObservabilityError> {
         289  +
        match self.meter_provider.force_flush() {
         290  +
            Ok(_) => Ok(()),
         291  +
            Err(err) => Err(ObservabilityError::new(ErrorKind::MetricsFlush, err)),
         292  +
        }
         293  +
    }
         294  +
         295  +
    /// Gracefully shutdown the metric pipeline.
         296  +
    pub fn shutdown(&self) -> Result<(), ObservabilityError> {
         297  +
        match self.meter_provider.force_flush() {
         298  +
            Ok(_) => Ok(()),
         299  +
            Err(err) => Err(ObservabilityError::new(ErrorKind::MetricsShutdown, err)),
         300  +
        }
         301  +
    }
         302  +
}
         303  +
         304  +
impl ProvideMeter for AwsSdkOtelMeterProvider {
         305  +
    fn get_meter(&self, scope: &'static str, _attributes: Option<&Attributes>) -> Arc<dyn Meter> {
         306  +
        Arc::new(MeterWrap(self.meter_provider.meter(scope)))
         307  +
    }
         308  +
         309  +
    fn as_any(&self) -> &dyn std::any::Any {
         310  +
        self
         311  +
    }
         312  +
}
         313  +
         314  +
#[cfg(test)]
         315  +
mod tests {
         316  +
         317  +
    use aws_smithy_observability::attributes::{AttributeValue, Attributes};
         318  +
    use aws_smithy_observability::meter::AsyncMeasure;
         319  +
    use aws_smithy_observability::provider::TelemetryProvider;
         320  +
    use opentelemetry_sdk::metrics::{
         321  +
        data::{Gauge, Histogram, Sum},
         322  +
        PeriodicReader, SdkMeterProvider,
         323  +
    };
         324  +
    use opentelemetry_sdk::runtime::Tokio;
         325  +
    use opentelemetry_sdk::testing::metrics::InMemoryMetricsExporter;
         326  +
         327  +
    use super::AwsSdkOtelMeterProvider;
         328  +
         329  +
    // Without these tokio settings this test just stalls forever on flushing the metrics pipeline
         330  +
    #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
         331  +
    async fn sync_instruments_work() {
         332  +
        // Create the OTel metrics objects
         333  +
        let exporter = InMemoryMetricsExporter::default();
         334  +
        let reader = PeriodicReader::builder(exporter.clone(), Tokio).build();
         335  +
        let otel_mp = SdkMeterProvider::builder().with_reader(reader).build();
         336  +
         337  +
        // Create the SDK metrics types from the OTel objects
         338  +
        let sdk_mp = AwsSdkOtelMeterProvider::new(otel_mp);
         339  +
        let sdk_tp = TelemetryProvider::builder().meter_provider(sdk_mp).build();
         340  +
         341  +
        // Get the dyn versions of the SDK metrics objects
         342  +
        let dyn_sdk_mp = sdk_tp.meter_provider();
         343  +
        let dyn_sdk_meter = dyn_sdk_mp.get_meter("TestMeter", None);
         344  +
         345  +
        //Create all 3 sync instruments and record some data for each
         346  +
        let mono_counter =
         347  +
            dyn_sdk_meter.create_monotonic_counter("TestMonoCounter".to_string(), None, None);
         348  +
        mono_counter.add(4, None, None);
         349  +
        let ud_counter =
         350  +
            dyn_sdk_meter.create_up_down_counter("TestUpDownCounter".to_string(), None, None);
         351  +
        ud_counter.add(-6, None, None);
         352  +
        let histogram = dyn_sdk_meter.create_histogram("TestHistogram".to_string(), None, None);
         353  +
        histogram.record(1.234, None, None);
         354  +
         355  +
        // Gracefully shutdown the metrics provider so all metrics are flushed through the pipeline
         356  +
        dyn_sdk_mp
         357  +
            .as_any()
         358  +
            .downcast_ref::<AwsSdkOtelMeterProvider>()
         359  +
            .unwrap()
         360  +
            .shutdown()
         361  +
            .unwrap();
         362  +
         363  +
        // Extract the metrics from the exporter and assert that they are what we expect
         364  +
        let finished_metrics = exporter.get_finished_metrics().unwrap();
         365  +
        let extracted_mono_counter_data = &finished_metrics[0].scope_metrics[0].metrics[0]
         366  +
            .data
         367  +
            .as_any()
         368  +
            .downcast_ref::<Sum<u64>>()
         369  +
            .unwrap()
         370  +
            .data_points[0]
         371  +
            .value;
         372  +
        assert_eq!(extracted_mono_counter_data, &4);
         373  +
         374  +
        let extracted_ud_counter_data = &finished_metrics[0].scope_metrics[0].metrics[1]
         375  +
            .data
         376  +
            .as_any()
         377  +
            .downcast_ref::<Sum<i64>>()
         378  +
            .unwrap()
         379  +
            .data_points[0]
         380  +
            .value;
         381  +
        assert_eq!(extracted_ud_counter_data, &-6);
         382  +
         383  +
        let extracted_histogram_data = &finished_metrics[0].scope_metrics[0].metrics[2]
         384  +
            .data
         385  +
            .as_any()
         386  +
            .downcast_ref::<Histogram<f64>>()
         387  +
            .unwrap()
         388  +
            .data_points[0]
         389  +
            .sum;
         390  +
        assert_eq!(extracted_histogram_data, &1.234);
         391  +
    }
         392  +
         393  +
    #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
         394  +
    async fn async_instrument_work() {
         395  +
        // Create the OTel metrics objects
         396  +
        let exporter = InMemoryMetricsExporter::default();
         397  +
        let reader = PeriodicReader::builder(exporter.clone(), Tokio).build();
         398  +
        let otel_mp = SdkMeterProvider::builder().with_reader(reader).build();
         399  +
         400  +
        // Create the SDK metrics types from the OTel objects
         401  +
        let sdk_mp = AwsSdkOtelMeterProvider::new(otel_mp);
         402  +
        let sdk_tp = TelemetryProvider::builder().meter_provider(sdk_mp).build();
         403  +
         404  +
        // Get the dyn versions of the SDK metrics objects
         405  +
        let dyn_sdk_mp = sdk_tp.meter_provider();
         406  +
        let dyn_sdk_meter = dyn_sdk_mp.get_meter("TestMeter", None);
         407  +
         408  +
        //Create all async instruments and record some data
         409  +
        let gauge = dyn_sdk_meter.create_gauge(
         410  +
            "TestGauge".to_string(),
         411  +
            // Callback function records another value with different attributes so it is deduped
         412  +
            Box::new(|measurement: &dyn AsyncMeasure<Value = f64>| {
         413  +
                let mut attrs = Attributes::new();
         414  +
                attrs.set(
         415  +
                    "TestGaugeAttr",
         416  +
                    AttributeValue::String("TestGaugeAttr".into()),
         417  +
                );
         418  +
                measurement.record(6.789, Some(&attrs), None);
         419  +
            }),
         420  +
            None,
         421  +
            None,
         422  +
        );
         423  +
        gauge.record(1.234, None, None);
         424  +
         425  +
        let async_ud_counter = dyn_sdk_meter.create_async_up_down_counter(
         426  +
            "TestAsyncUpDownCounter".to_string(),
         427  +
            Box::new(|measurement: &dyn AsyncMeasure<Value = i64>| {
         428  +
                let mut attrs = Attributes::new();
         429  +
                attrs.set(
         430  +
                    "TestAsyncUpDownCounterAttr",
         431  +
                    AttributeValue::String("TestAsyncUpDownCounterAttr".into()),
         432  +
                );
         433  +
                measurement.record(12, Some(&attrs), None);
         434  +
            }),
         435  +
            None,
         436  +
            None,
         437  +
        );
         438  +
        async_ud_counter.record(-6, None, None);
         439  +
         440  +
        let async_mono_counter = dyn_sdk_meter.create_async_monotonic_counter(
         441  +
            "TestAsyncMonoCounter".to_string(),
         442  +
            Box::new(|measurement: &dyn AsyncMeasure<Value = u64>| {
         443  +
                let mut attrs = Attributes::new();
         444  +
                attrs.set(
         445  +
                    "TestAsyncMonoCounterAttr",
         446  +
                    AttributeValue::String("TestAsyncMonoCounterAttr".into()),
         447  +
                );
         448  +
                measurement.record(123, Some(&attrs), None);
         449  +
            }),
         450  +
            None,
         451  +
            None,
         452  +
        );
         453  +
        async_mono_counter.record(4, None, None);
         454  +
         455  +
        // Gracefully shutdown the metrics provider so all metrics are flushed through the pipeline
         456  +
        dyn_sdk_mp
         457  +
            .as_any()
         458  +
            .downcast_ref::<AwsSdkOtelMeterProvider>()
         459  +
            .unwrap()
         460  +
            .shutdown()
         461  +
            .unwrap();
         462  +
         463  +
        // Extract the metrics from the exporter
         464  +
        let finished_metrics = exporter.get_finished_metrics().unwrap();
         465  +
         466  +
        // Assert that the reported metrics are what we expect
         467  +
        let extracted_gauge_data = &finished_metrics[0].scope_metrics[0].metrics[0]
         468  +
            .data
         469  +
            .as_any()
         470  +
            .downcast_ref::<Gauge<f64>>()
         471  +
            .unwrap()
         472  +
            .data_points[0]
         473  +
            .value;
         474  +
        assert_eq!(extracted_gauge_data, &1.234);
         475  +
         476  +
        let extracted_async_ud_counter_data = &finished_metrics[0].scope_metrics[0].metrics[1]
         477  +
            .data
         478  +
            .as_any()
         479  +
            .downcast_ref::<Sum<i64>>()
         480  +
            .unwrap()
         481  +
            .data_points[0]
         482  +
            .value;
         483  +
        assert_eq!(extracted_async_ud_counter_data, &-6);
         484  +
         485  +
        let extracted_async_mono_data = &finished_metrics[0].scope_metrics[0].metrics[2]
         486  +
            .data
         487  +
            .as_any()
         488  +
            .downcast_ref::<Sum<u64>>()
         489  +
            .unwrap()
         490  +
            .data_points[0]
         491  +
            .value;
         492  +
        assert_eq!(extracted_async_mono_data, &4);
         493  +
         494  +
        // Assert that the async callbacks ran
         495  +
        let finished_metrics = exporter.get_finished_metrics().unwrap();
         496  +
        let extracted_gauge_data = &finished_metrics[0].scope_metrics[0].metrics[0]
         497  +
            .data
         498  +
            .as_any()
         499  +
            .downcast_ref::<Gauge<f64>>()
         500  +
            .unwrap()
         501  +
            .data_points[1]
         502  +
            .value;
         503  +
        assert_eq!(extracted_gauge_data, &6.789);
         504  +
         505  +
        let extracted_async_ud_counter_data = &finished_metrics[0].scope_metrics[0].metrics[1]
         506  +
            .data
         507  +
            .as_any()
         508  +
            .downcast_ref::<Sum<i64>>()
         509  +
            .unwrap()
         510  +
            .data_points[1]
         511  +
            .value;
         512  +
        assert_eq!(extracted_async_ud_counter_data, &12);
         513  +
         514  +
        let extracted_async_mono_data = &finished_metrics[0].scope_metrics[0].metrics[2]
         515  +
            .data
         516  +
            .as_any()
         517  +
            .downcast_ref::<Sum<u64>>()
         518  +
            .unwrap()
         519  +
            .data_points[1]
         520  +
            .value;
         521  +
        assert_eq!(extracted_async_mono_data, &123);
         522  +
    }
         523  +
}

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-observability/Cargo.toml

@@ -0,1 +0,24 @@
           1  +
# Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
           2  +
[package]
           3  +
name = "aws-smithy-observability"
           4  +
version = "0.1.0"
           5  +
authors = ["AWS Rust SDK Team <aws-sdk-rust@amazon.com>"]
           6  +
description = "Smithy observability implementation."
           7  +
edition = "2021"
           8  +
license = "Apache-2.0"
           9  +
repository = "https://github.com/awslabs/smithy-rs"
          10  +
[package.metadata.docs.rs]
          11  +
all-features = true
          12  +
targets = ["x86_64-unknown-linux-gnu"]
          13  +
cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]
          14  +
rustdoc-args = ["--cfg", "docsrs"]
          15  +
          16  +
[dependencies]
          17  +
once_cell = "1.19.0"
          18  +
          19  +
[dependencies.aws-smithy-runtime-api]
          20  +
path = "../aws-smithy-runtime-api"
          21  +
version = "1.7.3"
          22  +
          23  +
[dev-dependencies]
          24  +
serial_test = "3.1.1"

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-observability/LICENSE

@@ -0,1 +0,175 @@
           1  +
           2  +
                                 Apache License
           3  +
                           Version 2.0, January 2004
           4  +
                        http://www.apache.org/licenses/
           5  +
           6  +
   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
           7  +
           8  +
   1. Definitions.
           9  +
          10  +
      "License" shall mean the terms and conditions for use, reproduction,
          11  +
      and distribution as defined by Sections 1 through 9 of this document.
          12  +
          13  +
      "Licensor" shall mean the copyright owner or entity authorized by
          14  +
      the copyright owner that is granting the License.
          15  +
          16  +
      "Legal Entity" shall mean the union of the acting entity and all
          17  +
      other entities that control, are controlled by, or are under common
          18  +
      control with that entity. For the purposes of this definition,
          19  +
      "control" means (i) the power, direct or indirect, to cause the
          20  +
      direction or management of such entity, whether by contract or
          21  +
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
          22  +
      outstanding shares, or (iii) beneficial ownership of such entity.
          23  +
          24  +
      "You" (or "Your") shall mean an individual or Legal Entity
          25  +
      exercising permissions granted by this License.
          26  +
          27  +
      "Source" form shall mean the preferred form for making modifications,
          28  +
      including but not limited to software source code, documentation
          29  +
      source, and configuration files.
          30  +
          31  +
      "Object" form shall mean any form resulting from mechanical
          32  +
      transformation or translation of a Source form, including but
          33  +
      not limited to compiled object code, generated documentation,
          34  +
      and conversions to other media types.
          35  +
          36  +
      "Work" shall mean the work of authorship, whether in Source or
          37  +
      Object form, made available under the License, as indicated by a
          38  +
      copyright notice that is included in or attached to the work
          39  +
      (an example is provided in the Appendix below).
          40  +
          41  +
      "Derivative Works" shall mean any work, whether in Source or Object
          42  +
      form, that is based on (or derived from) the Work and for which the
          43  +
      editorial revisions, annotations, elaborations, or other modifications
          44  +
      represent, as a whole, an original work of authorship. For the purposes
          45  +
      of this License, Derivative Works shall not include works that remain
          46  +
      separable from, or merely link (or bind by name) to the interfaces of,
          47  +
      the Work and Derivative Works thereof.
          48  +
          49  +
      "Contribution" shall mean any work of authorship, including
          50  +
      the original version of the Work and any modifications or additions
          51  +
      to that Work or Derivative Works thereof, that is intentionally
          52  +
      submitted to Licensor for inclusion in the Work by the copyright owner
          53  +
      or by an individual or Legal Entity authorized to submit on behalf of
          54  +
      the copyright owner. For the purposes of this definition, "submitted"
          55  +
      means any form of electronic, verbal, or written communication sent
          56  +
      to the Licensor or its representatives, including but not limited to
          57  +
      communication on electronic mailing lists, source code control systems,
          58  +
      and issue tracking systems that are managed by, or on behalf of, the
          59  +
      Licensor for the purpose of discussing and improving the Work, but
          60  +
      excluding communication that is conspicuously marked or otherwise
          61  +
      designated in writing by the copyright owner as "Not a Contribution."
          62  +
          63  +
      "Contributor" shall mean Licensor and any individual or Legal Entity
          64  +
      on behalf of whom a Contribution has been received by Licensor and
          65  +
      subsequently incorporated within the Work.
          66  +
          67  +
   2. Grant of Copyright License. Subject to the terms and conditions of
          68  +
      this License, each Contributor hereby grants to You a perpetual,
          69  +
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
          70  +
      copyright license to reproduce, prepare Derivative Works of,
          71  +
      publicly display, publicly perform, sublicense, and distribute the
          72  +
      Work and such Derivative Works in Source or Object form.
          73  +
          74  +
   3. Grant of Patent License. Subject to the terms and conditions of
          75  +
      this License, each Contributor hereby grants to You a perpetual,
          76  +
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
          77  +
      (except as stated in this section) patent license to make, have made,
          78  +
      use, offer to sell, sell, import, and otherwise transfer the Work,
          79  +
      where such license applies only to those patent claims licensable
          80  +
      by such Contributor that are necessarily infringed by their
          81  +
      Contribution(s) alone or by combination of their Contribution(s)
          82  +
      with the Work to which such Contribution(s) was submitted. If You
          83  +
      institute patent litigation against any entity (including a
          84  +
      cross-claim or counterclaim in a lawsuit) alleging that the Work
          85  +
      or a Contribution incorporated within the Work constitutes direct
          86  +
      or contributory patent infringement, then any patent licenses
          87  +
      granted to You under this License for that Work shall terminate
          88  +
      as of the date such litigation is filed.
          89  +
          90  +
   4. Redistribution. You may reproduce and distribute copies of the
          91  +
      Work or Derivative Works thereof in any medium, with or without
          92  +
      modifications, and in Source or Object form, provided that You
          93  +
      meet the following conditions:
          94  +
          95  +
      (a) You must give any other recipients of the Work or
          96  +
          Derivative Works a copy of this License; and
          97  +
          98  +
      (b) You must cause any modified files to carry prominent notices
          99  +
          stating that You changed the files; and
         100  +
         101  +
      (c) You must retain, in the Source form of any Derivative Works
         102  +
          that You distribute, all copyright, patent, trademark, and
         103  +
          attribution notices from the Source form of the Work,
         104  +
          excluding those notices that do not pertain to any part of
         105  +
          the Derivative Works; and
         106  +
         107  +
      (d) If the Work includes a "NOTICE" text file as part of its
         108  +
          distribution, then any Derivative Works that You distribute must
         109  +
          include a readable copy of the attribution notices contained
         110  +
          within such NOTICE file, excluding those notices that do not
         111  +
          pertain to any part of the Derivative Works, in at least one
         112  +
          of the following places: within a NOTICE text file distributed
         113  +
          as part of the Derivative Works; within the Source form or
         114  +
          documentation, if provided along with the Derivative Works; or,
         115  +
          within a display generated by the Derivative Works, if and
         116  +
          wherever such third-party notices normally appear. The contents
         117  +
          of the NOTICE file are for informational purposes only and
         118  +
          do not modify the License. You may add Your own attribution
         119  +
          notices within Derivative Works that You distribute, alongside
         120  +
          or as an addendum to the NOTICE text from the Work, provided
         121  +
          that such additional attribution notices cannot be construed
         122  +
          as modifying the License.
         123  +
         124  +
      You may add Your own copyright statement to Your modifications and
         125  +
      may provide additional or different license terms and conditions
         126  +
      for use, reproduction, or distribution of Your modifications, or
         127  +
      for any such Derivative Works as a whole, provided Your use,
         128  +
      reproduction, and distribution of the Work otherwise complies with
         129  +
      the conditions stated in this License.
         130  +
         131  +
   5. Submission of Contributions. Unless You explicitly state otherwise,
         132  +
      any Contribution intentionally submitted for inclusion in the Work
         133  +
      by You to the Licensor shall be under the terms and conditions of
         134  +
      this License, without any additional terms or conditions.
         135  +
      Notwithstanding the above, nothing herein shall supersede or modify
         136  +
      the terms of any separate license agreement you may have executed
         137  +
      with Licensor regarding such Contributions.
         138  +
         139  +
   6. Trademarks. This License does not grant permission to use the trade
         140  +
      names, trademarks, service marks, or product names of the Licensor,
         141  +
      except as required for reasonable and customary use in describing the
         142  +
      origin of the Work and reproducing the content of the NOTICE file.
         143  +
         144  +
   7. Disclaimer of Warranty. Unless required by applicable law or
         145  +
      agreed to in writing, Licensor provides the Work (and each
         146  +
      Contributor provides its Contributions) on an "AS IS" BASIS,
         147  +
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
         148  +
      implied, including, without limitation, any warranties or conditions
         149  +
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
         150  +
      PARTICULAR PURPOSE. You are solely responsible for determining the
         151  +
      appropriateness of using or redistributing the Work and assume any
         152  +
      risks associated with Your exercise of permissions under this License.
         153  +
         154  +
   8. Limitation of Liability. In no event and under no legal theory,
         155  +
      whether in tort (including negligence), contract, or otherwise,
         156  +
      unless required by applicable law (such as deliberate and grossly
         157  +
      negligent acts) or agreed to in writing, shall any Contributor be
         158  +
      liable to You for damages, including any direct, indirect, special,
         159  +
      incidental, or consequential damages of any character arising as a
         160  +
      result of this License or out of the use or inability to use the
         161  +
      Work (including but not limited to damages for loss of goodwill,
         162  +
      work stoppage, computer failure or malfunction, or any and all
         163  +
      other commercial damages or losses), even if such Contributor
         164  +
      has been advised of the possibility of such damages.
         165  +
         166  +
   9. Accepting Warranty or Additional Liability. While redistributing
         167  +
      the Work or Derivative Works thereof, You may choose to offer,
         168  +
      and charge a fee for, acceptance of support, warranty, indemnity,
         169  +
      or other liability obligations and/or rights consistent with this
         170  +
      License. However, in accepting such obligations, You may act only
         171  +
      on Your own behalf and on Your sole responsibility, not on behalf
         172  +
      of any other Contributor, and only if You agree to indemnify,
         173  +
      defend, and hold each Contributor harmless for any liability
         174  +
      incurred by, or claims asserted against, such Contributor by reason
         175  +
      of your accepting any such warranty or additional liability.