From 2c5d4538822ef30894a39a5d8b60ff95759f0b61 Mon Sep 17 00:00:00 2001 From: Levi Morrison Date: Tue, 28 May 2024 17:49:39 -0600 Subject: [PATCH 1/2] feat(common): add tag! macro This does a few things: 1. Creates a `tag!` macro which does compile-time checking for some invariants. 2. Changes a `Tag` to use `Cow<'static, str>` instead of a `String`. As libdatadog usage has grown, we have more Rust users of the lib and therefore more static Rust strs we can trust at compile-time and avoid runtime allocations. 3. Makes `Tag::from_value` private. Use `tag!` or `Tag::new`. --- Cargo.lock | 1 + LICENSE-3rdparty.yml | 12 +-- bin_tests/src/bin/crashtracker_bin_test.rs | 10 +- crashtracker/src/api.rs | 4 +- crashtracker/src/telemetry.rs | 10 +- ddcommon/Cargo.toml | 1 + ddcommon/src/tag.rs | 100 +++++++++++++++--- .../examples/tm-metrics-worker-test.rs | 4 +- ddtelemetry/examples/tm-worker-test.rs | 4 +- ddtelemetry/src/metrics.rs | 3 +- profiling-ffi/src/exporter.rs | 5 +- profiling/tests/form.rs | 6 +- sidecar/src/dogstatsd.rs | 8 +- sidecar/src/self_telemetry.rs | 7 +- 14 files changed, 120 insertions(+), 55 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1821a903f..7120c1061 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1450,6 +1450,7 @@ dependencies = [ "rustls", "rustls-native-certs", "serde", + "static_assertions", "tokio", "tokio-rustls", ] diff --git a/LICENSE-3rdparty.yml b/LICENSE-3rdparty.yml index a479f22ec..0c7ba048a 100644 --- a/LICENSE-3rdparty.yml +++ b/LICENSE-3rdparty.yml @@ -15684,16 +15684,16 @@ third_party_libraries: - package_name: ring package_version: 0.16.20 repository: https://github.com/briansmith/ring - license: License specified in file ($CARGO_HOME/registry/src/index.crates.io-6f17d22bba15001f/ring-0.16.20/LICENSE) + license: License specified in file ($CARGO_HOME/registry/src/github.com-1ecc6299db9ec823/ring-0.16.20/LICENSE) licenses: - - license: License specified in file ($CARGO_HOME/registry/src/index.crates.io-6f17d22bba15001f/ring-0.16.20/LICENSE) + - license: License specified in file ($CARGO_HOME/registry/src/github.com-1ecc6299db9ec823/ring-0.16.20/LICENSE) text: "Note that it is easy for this file to get out of sync with the licenses in the\nsource code files. It's recommended to compare the licenses in the source code\nwith what's mentioned here.\n\n*ring* is derived from BoringSSL, so the licensing situation in *ring* is\nsimilar to BoringSSL.\n\n*ring* uses an ISC-style license like BoringSSL for code in new files,\nincluding in particular all the Rust code:\n\n Copyright 2015-2016 Brian Smith.\n\n Permission to use, copy, modify, and/or distribute this software for any\n purpose with or without fee is hereby granted, provided that the above\n copyright notice and this permission notice appear in all copies.\n\n THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHORS DISCLAIM ALL WARRANTIES\n WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY\n SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION\n OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN\n CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\nBoringSSL is a fork of OpenSSL. As such, large parts of it fall under OpenSSL\nlicensing. Files that are completely new have a Google copyright and an ISC\nlicense. This license is reproduced at the bottom of this file.\n\nContributors to BoringSSL are required to follow the CLA rules for Chromium:\nhttps://cla.developers.google.com/clas\n\nFiles in third_party/ have their own licenses, as described therein. The MIT\nlicense, for third_party/fiat, which, unlike other third_party directories, is\ncompiled into non-test libraries, is included below.\n\nThe OpenSSL toolkit stays under a dual license, i.e. both the conditions of the\nOpenSSL License and the original SSLeay license apply to the toolkit. See below\nfor the actual license texts. Actually both licenses are BSD-style Open Source\nlicenses. In case of any license issues related to OpenSSL please contact\nopenssl-core@openssl.org.\n\nThe following are Google-internal bug numbers where explicit permission from\nsome authors is recorded for use of their work:\n 27287199\n 27287880\n 27287883\n\n OpenSSL License\n ---------------\n\n/* ====================================================================\n * Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer. \n *\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in\n * the documentation and/or other materials provided with the\n * distribution.\n *\n * 3. All advertising materials mentioning features or use of this\n * software must display the following acknowledgment:\n * \"This product includes software developed by the OpenSSL Project\n * for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"\n *\n * 4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n * endorse or promote products derived from this software without\n * prior written permission. For written permission, please contact\n * openssl-core@openssl.org.\n *\n * 5. Products derived from this software may not be called \"OpenSSL\"\n * nor may \"OpenSSL\" appear in their names without prior written\n * permission of the OpenSSL Project.\n *\n * 6. Redistributions of any form whatsoever must retain the following\n * acknowledgment:\n * \"This product includes software developed by the OpenSSL Project\n * for use in the OpenSSL Toolkit (http://www.openssl.org/)\"\n *\n * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n * ====================================================================\n *\n * This product includes cryptographic software written by Eric Young\n * (eay@cryptsoft.com). This product includes software written by Tim\n * Hudson (tjh@cryptsoft.com).\n *\n */\n\n Original SSLeay License\n -----------------------\n\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n * \n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to. The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code. The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n * \n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n * must display the following acknowledgement:\n * \"This product includes cryptographic software written by\n * Eric Young (eay@cryptsoft.com)\"\n * The word 'cryptographic' can be left out if the rouines from the library\n * being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from \n * the apps directory (application code) you must include an acknowledgement:\n * \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n * \n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n * \n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed. i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n\nISC license used for completely new code in BoringSSL:\n\n/* Copyright (c) 2015, Google Inc.\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY\n * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION\n * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN\n * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */\n\n\nThe code in third_party/fiat carries the MIT license:\n\nCopyright (c) 2015-2016 the fiat-crypto authors (see\nhttps://github.com/mit-plv/fiat-crypto/blob/master/AUTHORS).\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n" - package_name: ring package_version: 0.17.8 repository: https://github.com/briansmith/ring - license: License specified in file ($CARGO_HOME/registry/src/index.crates.io-6f17d22bba15001f/ring-0.17.8/LICENSE) + license: License specified in file ($CARGO_HOME/registry/src/github.com-1ecc6299db9ec823/ring-0.17.8/LICENSE) licenses: - - license: License specified in file ($CARGO_HOME/registry/src/index.crates.io-6f17d22bba15001f/ring-0.17.8/LICENSE) + - license: License specified in file ($CARGO_HOME/registry/src/github.com-1ecc6299db9ec823/ring-0.17.8/LICENSE) text: "Note that it is easy for this file to get out of sync with the licenses in the\nsource code files. It's recommended to compare the licenses in the source code\nwith what's mentioned here.\n\n*ring* is derived from BoringSSL, so the licensing situation in *ring* is\nsimilar to BoringSSL.\n\n*ring* uses an ISC-style license like BoringSSL for code in new files,\nincluding in particular all the Rust code:\n\n Copyright 2015-2016 Brian Smith.\n\n Permission to use, copy, modify, and/or distribute this software for any\n purpose with or without fee is hereby granted, provided that the above\n copyright notice and this permission notice appear in all copies.\n\n THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHORS DISCLAIM ALL WARRANTIES\n WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY\n SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION\n OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN\n CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\nBoringSSL is a fork of OpenSSL. As such, large parts of it fall under OpenSSL\nlicensing. Files that are completely new have a Google copyright and an ISC\nlicense. This license is reproduced at the bottom of this file.\n\nContributors to BoringSSL are required to follow the CLA rules for Chromium:\nhttps://cla.developers.google.com/clas\n\nFiles in third_party/ have their own licenses, as described therein. The MIT\nlicense, for third_party/fiat, which, unlike other third_party directories, is\ncompiled into non-test libraries, is included below.\n\nThe OpenSSL toolkit stays under a dual license, i.e. both the conditions of the\nOpenSSL License and the original SSLeay license apply to the toolkit. See below\nfor the actual license texts. Actually both licenses are BSD-style Open Source\nlicenses. In case of any license issues related to OpenSSL please contact\nopenssl-core@openssl.org.\n\nThe following are Google-internal bug numbers where explicit permission from\nsome authors is recorded for use of their work:\n 27287199\n 27287880\n 27287883\n\n OpenSSL License\n ---------------\n\n/* ====================================================================\n * Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer. \n *\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in\n * the documentation and/or other materials provided with the\n * distribution.\n *\n * 3. All advertising materials mentioning features or use of this\n * software must display the following acknowledgment:\n * \"This product includes software developed by the OpenSSL Project\n * for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"\n *\n * 4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n * endorse or promote products derived from this software without\n * prior written permission. For written permission, please contact\n * openssl-core@openssl.org.\n *\n * 5. Products derived from this software may not be called \"OpenSSL\"\n * nor may \"OpenSSL\" appear in their names without prior written\n * permission of the OpenSSL Project.\n *\n * 6. Redistributions of any form whatsoever must retain the following\n * acknowledgment:\n * \"This product includes software developed by the OpenSSL Project\n * for use in the OpenSSL Toolkit (http://www.openssl.org/)\"\n *\n * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n * ====================================================================\n *\n * This product includes cryptographic software written by Eric Young\n * (eay@cryptsoft.com). This product includes software written by Tim\n * Hudson (tjh@cryptsoft.com).\n *\n */\n\n Original SSLeay License\n -----------------------\n\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n * \n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to. The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code. The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n * \n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n * must display the following acknowledgement:\n * \"This product includes cryptographic software written by\n * Eric Young (eay@cryptsoft.com)\"\n * The word 'cryptographic' can be left out if the rouines from the library\n * being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from \n * the apps directory (application code) you must include an acknowledgement:\n * \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n * \n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n * \n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed. i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n\nISC license used for completely new code in BoringSSL:\n\n/* Copyright (c) 2015, Google Inc.\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY\n * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION\n * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN\n * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */\n\n\nThe code in third_party/fiat carries the MIT license:\n\nCopyright (c) 2015-2016 the fiat-crypto authors (see\nhttps://github.com/mit-plv/fiat-crypto/blob/master/AUTHORS).\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n" - package_name: rmp package_version: 0.8.12 @@ -22617,9 +22617,9 @@ third_party_libraries: - package_name: webpki package_version: 0.22.4 repository: https://github.com/briansmith/webpki - license: License specified in file ($CARGO_HOME/registry/src/index.crates.io-6f17d22bba15001f/webpki-0.22.4/LICENSE) + license: License specified in file ($CARGO_HOME/registry/src/github.com-1ecc6299db9ec823/webpki-0.22.4/LICENSE) licenses: - - license: License specified in file ($CARGO_HOME/registry/src/index.crates.io-6f17d22bba15001f/webpki-0.22.4/LICENSE) + - license: License specified in file ($CARGO_HOME/registry/src/github.com-1ecc6299db9ec823/webpki-0.22.4/LICENSE) text: | Except as otherwise noted, this project is licensed under the following (ISC-style) terms: diff --git a/bin_tests/src/bin/crashtracker_bin_test.rs b/bin_tests/src/bin/crashtracker_bin_test.rs index 9d915d48a..96e9c4272 100644 --- a/bin_tests/src/bin/crashtracker_bin_test.rs +++ b/bin_tests/src/bin/crashtracker_bin_test.rs @@ -18,7 +18,7 @@ mod unix { self as crashtracker, CrashtrackerConfiguration, CrashtrackerMetadata, CrashtrackerReceiverConfig, }; - use datadog_profiling::exporter::Tag; + use ddcommon::tag; #[inline(never)] unsafe fn deref_ptr(p: *mut u8) { @@ -62,10 +62,10 @@ mod unix { profiling_library_version: "1.0.0".to_owned(), family: "native".to_owned(), tags: vec![ - Tag::new("service", "foo").unwrap(), - Tag::new("service_version", "bar").unwrap(), - Tag::new("runtime-id", "xyz").unwrap(), - Tag::new("language", "native").unwrap(), + tag!("service", "foo"), + tag!("service_version", "bar"), + tag!("runtime-id", "xyz"), + tag!("language", "native"), ], }, )?; diff --git a/crashtracker/src/api.rs b/crashtracker/src/api.rs index 6c475ec01..27bae87db 100644 --- a/crashtracker/src/api.rs +++ b/crashtracker/src/api.rs @@ -110,7 +110,7 @@ fn test_crash() { use crate::{begin_profiling_op, StacktraceCollection}; use chrono::Utc; use ddcommon::parse_uri; - use ddcommon::tag::Tag; + use ddcommon::tag; use ddcommon::Endpoint; use std::time::Duration; @@ -152,7 +152,7 @@ fn test_crash() { init(config, receiver_config, metadata).expect("not to fail"); begin_profiling_op(crate::ProfilingOpTypes::CollectingSample).expect("Not to fail"); - let tag = Tag::new("apple", "banana").expect("tag"); + let tag = tag!("apple", "banana"); let metadata2 = CrashtrackerMetadata::new( "libname".to_string(), "version".to_string(), diff --git a/crashtracker/src/telemetry.rs b/crashtracker/src/telemetry.rs index e0449fc30..a018a9d99 100644 --- a/crashtracker/src/telemetry.rs +++ b/crashtracker/src/telemetry.rs @@ -196,7 +196,7 @@ mod tests { use crate::SigInfo; use chrono::DateTime; - use ddcommon::{tag::Tag, Endpoint}; + use ddcommon::{tag, Endpoint}; use super::TelemetryCrashUploader; @@ -223,10 +223,10 @@ mod tests { profiling_library_version: "1.0.0".to_owned(), family: "native".to_owned(), tags: vec![ - Tag::new("service", "foo").unwrap(), - Tag::new("service_version", "bar").unwrap(), - Tag::new("runtime-id", "xyz").unwrap(), - Tag::new("language", "native").unwrap(), + tag!("service", "foo"), + tag!("service_version", "bar"), + tag!("runtime-id", "xyz"), + tag!("language", "native"), ], } } diff --git a/ddcommon/Cargo.toml b/ddcommon/Cargo.toml index f60454dbb..149155c97 100644 --- a/ddcommon/Cargo.toml +++ b/ddcommon/Cargo.toml @@ -38,6 +38,7 @@ rustls-native-certs = { version = "0.6" } tokio = { version = "1.23", features = ["rt", "macros"] } tokio-rustls = { version = "0.23" } serde = { version = "1.0", features = ["derive"] } +static_assertions = "1.1.0" [dev-dependencies] indexmap = "2.2" diff --git a/ddcommon/src/tag.rs b/ddcommon/src/tag.rs index 8efde9ef0..54cf5a32b 100644 --- a/ddcommon/src/tag.rs +++ b/ddcommon/src/tag.rs @@ -1,15 +1,72 @@ // Copyright 2021-Present Datadog, Inc. https://www.datadoghq.com/ // SPDX-License-Identifier: Apache-2.0 +use serde::{Deserialize, Serialize}; use std::borrow::Cow; use std::fmt::{Debug, Display, Formatter}; -use serde::{Deserialize, Serialize}; +pub use static_assertions::{const_assert, const_assert_ne}; #[derive(Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] #[serde(transparent)] pub struct Tag { - value: String, + /// Many tags are made from literal strings, such as: + /// - "language:native" + /// - "src_library:libdatadog" + /// - "type:timeout" + /// So being able to save allocations is nice. + value: Cow<'static, str>, +} + +impl Tag { + /// Used by the `tag!` macro. Not meant to be used directly, please use + /// the macro instead. + /// # Safety + /// Do not use directly, use through the `tag!` macro which enforces the + /// safety invariants at compile time. + pub const unsafe fn from_static_unchecked(value: &'static str) -> Self { + Self { + value: Cow::Borrowed(value), + } + } +} + +/// Creates a tag from a key and value known at compile-time, and fails to +/// compile if it's known to be invalid (it may still emit an invalid tag, not +/// all tag validation is currently done client-side). If the key or value +/// aren't known at compile-time, then use [Tag::new]. +// todo: what's a good way to keep these in-sync with Tag::from_value? +// This can be a little more strict because it's compitle-time evaluated. +// https://docs.datadoghq.com/getting_started/tagging/#define-tags +#[macro_export] +macro_rules! tag { + ($key:expr, $val:expr) => {{ + // Keys come in "value" or "key:value" format. This pattern is always + // the key:value format, which means the value should not be empty. + // todo: the implementation here differs subtly from Tag::from_value, + // which checks that the whole thing doesn't end with a colon. + $crate::tag::const_assert!(!$val.is_empty()); + + const COMBINED: &'static str = concat!($key, ":", $val); + + // Tags must start with a letter. This is more restrictive than is + // required (could be a unicode alphabetic char) and can be lifted + // if it's causing problems. + $crate::tag::const_assert!(COMBINED.as_bytes()[0].is_ascii_alphabetic()); + + // Tags can be up to 200 characters long and support Unicode letters + // (which includes most character sets, including languages such as + // Japanese). + // Presently, engineers interpretted this to be 200 bytes, not unicode + // characters. However, if the 200th character is unicode, it's + // allowed to spill over due to a historical bug. For now, we'll + // ignore this and hard-code 200 bytes. + $crate::tag::const_assert!(COMBINED.as_bytes().len() <= 200); + + #[allow(unused_unsafe)] + let tag = unsafe { $crate::tag::Tag::from_static_unchecked(COMBINED) }; + tag + }}; } impl Debug for Tag { @@ -32,9 +89,8 @@ impl Display for Tag { } impl Tag { - /// It's recommended to use Tag::new when possible, as tags that are in - /// the : format are preferred. - pub fn from_value<'a, IntoCow>(chunk: IntoCow) -> Result> + /// Validates a tag. + fn from_value<'a, IntoCow>(chunk: IntoCow) -> Result> where IntoCow: Into>, { @@ -61,11 +117,12 @@ impl Tag { return Err(format!("tag '{chunk}' ends with a colon").into()); } - Ok(Tag { - value: chunk.into_owned(), - }) + let value = Cow::Owned(chunk.into_owned()); + Ok(Tag { value }) } + /// Creates a tag from a key and value. It's preferred to use the `tag!` + /// macro when the key and value are both known at compile-time. pub fn new(key: K, value: V) -> Result> where K: AsRef, @@ -118,7 +175,16 @@ pub fn parse_tags(str: &str) -> (Vec, Option) { #[cfg(test)] mod tests { - use super::{parse_tags, Tag}; + use super::*; + + #[test] + fn test_is_send() { + // fails to compile if false + fn is_send(_t: T) -> bool { + true + } + assert!(is_send(tag!("src_library", "libdatadog"))); + } #[test] fn test_empty_key() { @@ -134,20 +200,22 @@ mod tests { fn test_bad_utf8() { // 0b1111_0xxx is the start of a 4-byte sequence, but there aren't any // more chars, so it will get converted into the utf8 replacement - // character. This results in a string with a space (32) and a - // replacement char, so it should be an error (no valid chars). - // However, we don't enforce many things about tags yet, so we let it - // slide. - let bytes = &[32, 0b1111_0111]; + // character. This results in a string with an "a" and a replacement + // char, so it should be an error (no valid chars). However, we don't + // enforce many things about tags yet client-side, so we let it slide. + let bytes = &[b'a', 0b1111_0111]; let key = String::from_utf8_lossy(bytes); let t = Tag::new(key, "value").unwrap(); - assert_eq!(" \u{FFFD}:value", t.to_string()); + assert_eq!("a\u{FFFD}:value", t.to_string()); } #[test] fn test_value_has_colon() { let result = Tag::new("env", "staging:east").expect("values can have colons"); assert_eq!("env:staging:east", result.to_string()); + + let result = tag!("env", "staging:east"); + assert_eq!("env:staging:east", result.to_string()); } #[test] @@ -156,7 +224,7 @@ mod tests { // that profile tags will then differ or cause failures compared to // trace tags. These require cross-team, cross-language collaboration. let cases = [ - (" begins with non-letter".to_string(), "value"), + ("_begins_with_non-letter".to_string(), "value"), ("the-tag-length-is-over-200-characters".repeat(6), "value"), ]; diff --git a/ddtelemetry/examples/tm-metrics-worker-test.rs b/ddtelemetry/examples/tm-metrics-worker-test.rs index 3989524b8..14b295c26 100644 --- a/ddtelemetry/examples/tm-metrics-worker-test.rs +++ b/ddtelemetry/examples/tm-metrics-worker-test.rs @@ -3,7 +3,7 @@ use std::{error::Error, time::Duration, time::Instant}; -use ddcommon::tag::Tag; +use ddcommon::tag; use ddtelemetry::{data, worker}; macro_rules! timeit { @@ -64,7 +64,7 @@ fn main() -> Result<(), Box> { handle.add_point(1.0, &dist_metric, Vec::new()).unwrap(); handle.add_point(2.0, &dist_metric, Vec::new()).unwrap(); - let tags = vec![Tag::from_value("foo:bar").unwrap()]; + let tags = vec![tag!("foo", "bar")]; handle.add_point(2.0, &ping_metric, tags.clone()).unwrap(); handle.add_point(1.8, &dist_metric, tags).unwrap(); diff --git a/ddtelemetry/examples/tm-worker-test.rs b/ddtelemetry/examples/tm-worker-test.rs index 318161569..d041c3921 100644 --- a/ddtelemetry/examples/tm-worker-test.rs +++ b/ddtelemetry/examples/tm-worker-test.rs @@ -6,7 +6,7 @@ use std::{ time::{Duration, Instant}, }; -use ddcommon::tag::Tag; +use ddcommon::tag; use ddtelemetry::{data, worker}; macro_rules! timeit { @@ -67,7 +67,7 @@ fn main() -> Result<(), Box> { handle.add_point(1.0, &dist_metric, Vec::new()).unwrap(); handle.add_point(2.0, &dist_metric, Vec::new()).unwrap(); - let tags = vec![Tag::from_value("foo:bar").unwrap()]; + let tags = vec![tag!("foo", "bar")]; handle.add_point(2.0, &ping_metric, tags.clone()).unwrap(); handle.add_point(1.8, &dist_metric, tags).unwrap(); diff --git a/ddtelemetry/src/metrics.rs b/ddtelemetry/src/metrics.rs index 016c6f740..5072ae301 100644 --- a/ddtelemetry/src/metrics.rs +++ b/ddtelemetry/src/metrics.rs @@ -220,6 +220,7 @@ impl MetricContexts { #[cfg(test)] mod tests { + use ddcommon::tag; use std::fmt::Debug; use super::*; @@ -279,7 +280,7 @@ mod tests { false, MetricNamespace::Tracers, ); - let extra_tags = vec![Tag::from_value("service:foobar").unwrap()]; + let extra_tags = vec![tag!("service", "foobar")]; buckets.add_point(context_key_1, 0.1, Vec::new()); buckets.add_point(context_key_1, 0.2, Vec::new()); diff --git a/profiling-ffi/src/exporter.rs b/profiling-ffi/src/exporter.rs index dce878341..e45ec4712 100644 --- a/profiling-ffi/src/exporter.rs +++ b/profiling-ffi/src/exporter.rs @@ -461,6 +461,7 @@ pub unsafe extern "C" fn ddog_CancellationToken_drop(token: Option<&mut Cancella #[cfg(test)] mod tests { use super::*; + use ddcommon::tag; use ddcommon_ffi::Slice; use serde_json::json; @@ -510,9 +511,7 @@ mod tests { // which Miri cannot evaluate. #[cfg_attr(miri, ignore)] fn profile_exporter_new_and_delete() { - let mut tags = ddcommon_ffi::Vec::default(); - let host = Tag::new("host", "localhost").expect("static tags to be valid"); - tags.push(host); + let tags = vec![tag!("host", "localhost")].into(); let result = unsafe { ddog_prof_Exporter_new( diff --git a/profiling/tests/form.rs b/profiling/tests/form.rs index 3c26bdcd1..6b17ae605 100644 --- a/profiling/tests/form.rs +++ b/profiling/tests/form.rs @@ -60,13 +60,11 @@ fn multipart( mod tests { use crate::multipart; use datadog_profiling::exporter::*; + use ddcommon::tag; use serde_json::json; fn default_tags() -> Vec { - vec![ - Tag::new("service", "php").expect("static tags to be valid"), - Tag::new("host", "bits").expect("static tags to be valid"), - ] + vec![tag!("service", "php"), tag!("host", "bits")] } fn parsed_event_json(request: Request) -> serde_json::Value { diff --git a/sidecar/src/dogstatsd.rs b/sidecar/src/dogstatsd.rs index 00d3ab22c..2fe020aa9 100644 --- a/sidecar/src/dogstatsd.rs +++ b/sidecar/src/dogstatsd.rs @@ -166,7 +166,7 @@ mod test { #[cfg(unix)] use ddcommon::connector::uds::socket_path_to_uri; use ddcommon::tag::Tag; - use ddcommon::Endpoint; + use ddcommon::{tag, Endpoint}; use http::Uri; use std::net; use std::time::Duration; @@ -189,11 +189,7 @@ mod test { api_key: None, }); flusher.send(vec![ - Count( - "test_count".to_string(), - 3, - vec![Tag::new("foo", "bar").unwrap()], - ), + Count("test_count".to_string(), 3, vec![tag!("foo", "bar")]), Count("test_neg_count".to_string(), -2, vec![]), Distribution("test_distribution".to_string(), 4.2, vec![]), Gauge("test_gauge".to_string(), 7.6, vec![]), diff --git a/sidecar/src/self_telemetry.rs b/sidecar/src/self_telemetry.rs index 3e5f0e113..2aee881a1 100644 --- a/sidecar/src/self_telemetry.rs +++ b/sidecar/src/self_telemetry.rs @@ -4,6 +4,7 @@ use crate::config::Config; use crate::log; use crate::service::SidecarServer; use crate::watchdog::WatchdogHandle; +use ddcommon::tag; use ddcommon::tag::Tag; use ddtelemetry::data::metrics::{MetricNamespace, MetricType}; use ddtelemetry::metrics::ContextKey; @@ -80,21 +81,21 @@ impl<'a> MetricData<'a> { futures.push(self.send( self.trace_api_errors, trace_metrics.api_errors_network as f64, - vec![Tag::new("type", "network").unwrap()], + vec![tag!("type", "network")], )); } if trace_metrics.api_errors_timeout > 0 { futures.push(self.send( self.trace_api_errors, trace_metrics.api_errors_timeout as f64, - vec![Tag::new("type", "timeout").unwrap()], + vec![tag!("type", "timeout")], )); } if trace_metrics.api_errors_status_code > 0 { futures.push(self.send( self.trace_api_errors, trace_metrics.api_errors_status_code as f64, - vec![Tag::new("type", "status_code").unwrap()], + vec![tag!("type", "status_code")], )); } for (status_code, count) in &trace_metrics.api_responses_count_per_code { From 708212bc99fe09898d6f48b29bf7881198604748 Mon Sep 17 00:00:00 2001 From: Levi Morrison Date: Thu, 30 May 2024 10:07:31 -0600 Subject: [PATCH 2/2] refactor: use anyhow::ensure and Result --- ddcommon-ffi/src/tags.rs | 2 +- ddcommon/src/tag.rs | 21 +++++++++------------ sidecar/src/dogstatsd.rs | 7 +------ 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/ddcommon-ffi/src/tags.rs b/ddcommon-ffi/src/tags.rs index df2799d12..d2bee8941 100644 --- a/ddcommon-ffi/src/tags.rs +++ b/ddcommon-ffi/src/tags.rs @@ -42,7 +42,7 @@ pub unsafe extern "C" fn ddog_Vec_Tag_push( vec.push(tag); PushTagResult::Ok } - Err(err) => PushTagResult::Err(Error::from(err.as_ref())), + Err(err) => PushTagResult::Err(Error::from(err.to_string())), } } diff --git a/ddcommon/src/tag.rs b/ddcommon/src/tag.rs index 54cf5a32b..17f2b691b 100644 --- a/ddcommon/src/tag.rs +++ b/ddcommon/src/tag.rs @@ -90,7 +90,7 @@ impl Display for Tag { impl Tag { /// Validates a tag. - fn from_value<'a, IntoCow>(chunk: IntoCow) -> Result> + fn from_value<'a, IntoCow>(chunk: IntoCow) -> anyhow::Result where IntoCow: Into>, { @@ -105,17 +105,14 @@ impl Tag { * are likely to be errors (such as passed in empty string). */ - if chunk.is_empty() { - return Err("tag is empty".into()); - } + anyhow::ensure!(!chunk.is_empty(), "tag is empty"); let mut chars = chunk.chars(); - if chars.next() == Some(':') { - return Err(format!("tag '{chunk}' begins with a colon").into()); - } - if chars.last() == Some(':') { - return Err(format!("tag '{chunk}' ends with a colon").into()); - } + anyhow::ensure!( + chars.next() != Some(':'), + "tag '{chunk}' begins with a colon" + ); + anyhow::ensure!(chars.last() != Some(':'), "tag '{chunk}' ends with a colon"); let value = Cow::Owned(chunk.into_owned()); Ok(Tag { value }) @@ -123,7 +120,7 @@ impl Tag { /// Creates a tag from a key and value. It's preferred to use the `tag!` /// macro when the key and value are both known at compile-time. - pub fn new(key: K, value: V) -> Result> + pub fn new(key: K, value: V) -> anyhow::Result where K: AsRef, V: AsRef, @@ -160,7 +157,7 @@ pub fn parse_tags(str: &str) -> (Vec, Option) { } else { error_message += ", "; } - error_message += err.as_ref(); + error_message += &err.to_string(); } } } diff --git a/sidecar/src/dogstatsd.rs b/sidecar/src/dogstatsd.rs index 2fe020aa9..65171ff5d 100644 --- a/sidecar/src/dogstatsd.rs +++ b/sidecar/src/dogstatsd.rs @@ -165,7 +165,6 @@ mod test { use crate::dogstatsd::{create_client, Flusher}; #[cfg(unix)] use ddcommon::connector::uds::socket_path_to_uri; - use ddcommon::tag::Tag; use ddcommon::{tag, Endpoint}; use http::Uri; use std::net; @@ -194,11 +193,7 @@ mod test { Distribution("test_distribution".to_string(), 4.2, vec![]), Gauge("test_gauge".to_string(), 7.6, vec![]), Histogram("test_histogram".to_string(), 8.0, vec![]), - Set( - "test_set".to_string(), - 9, - vec![Tag::new("the", "end").unwrap()], - ), + Set("test_set".to_string(), 9, vec![tag!("the", "end")]), Set("test_neg_set".to_string(), -1, vec![]), ]);