add otel library to ext

This commit is contained in:
Grant Limberg 2025-07-11 10:37:21 -07:00
parent 5fb8d2aa37
commit fbac205e65
No known key found for this signature in database
GPG key ID: 8F2F97D3BE8D7735
1289 changed files with 185182 additions and 0 deletions

View file

@ -0,0 +1,3 @@
third_party
tools
out

View file

@ -0,0 +1,41 @@
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
# bazel configurations for running tests under sanitizers.
# Based on https://github.com/bazelment/trunk/blob/master/tools/bazel.rc
# Enable automatic configs based on platform
common --enable_platform_specific_config
# Make globs that don't match anything fail
common --incompatible_disallow_empty_glob
# Needed by gRPC to build on some platforms.
build --copt -DGRPC_BAZEL_BUILD
# Workaround abseil libraries missing symbols
build:windows --dynamic_mode=off
# Set minimum supported C++ version
build:macos --host_cxxopt=-std=c++14 --cxxopt=-std=c++14
build:linux --host_cxxopt=-std=c++14 --cxxopt=-std=c++14
build:windows --host_cxxopt=/std:c++14 --cxxopt=/std:c++14
# --config=asan : Address Sanitizer.
common:asan --copt -DADDRESS_SANITIZER
common:asan --copt -fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,null,return,returns-nonnull-attribute,shift-exponent,signed-integer-overflow,unreachable,vla-bound
common:asan --copt -fsanitize-address-use-after-scope
common:asan --copt -fno-sanitize-recover=all
common:asan --linkopt -fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,null,return,returns-nonnull-attribute,shift-exponent,signed-integer-overflow,unreachable,vla-bound
common:asan --linkopt -fsanitize-address-use-after-scope
common:asan --linkopt -fno-sanitize-recover=all
common:asan --cc_output_directory_tag=asan
# --config=tsan : Thread Sanitizer.
common:tsan --copt -fsanitize=thread
common:tsan --copt -DTHREAD_SANITIZER
common:tsan --linkopt -fsanitize=thread
common:tsan --cc_output_directory_tag=tsan
# This is needed to address false positive problem with abseil.The same setting as gRPC
# https://github.com/google/sanitizers/issues/953
common:tsan --test_env=TSAN_OPTIONS=report_atomic_races=0

View file

@ -0,0 +1 @@
7.1.1

View file

@ -0,0 +1,73 @@
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
# See Clang docs: http://clang.llvm.org/docs/ClangFormatStyleOptions.html
BasedOnStyle: Chromium
# Allow double brackets such as std::vector<std::vector<int>>.
Standard: Cpp11
# Indent 2 spaces at a time.
IndentWidth: 2
# Keep lines under 100 columns long.
ColumnLimit: 100
# Always break before braces
BreakBeforeBraces: Custom
BraceWrapping:
# TODO(lujc) wait for clang-format-9 support in Chromium tools
# AfterCaseLabel: true
AfterClass: true
AfterControlStatement: true
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterStruct: true
AfterUnion: true
BeforeCatch: true
BeforeElse: true
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
# Keeps extern "C" blocks unindented.
AfterExternBlock: false
# Indent case labels.
IndentCaseLabels: true
# Right-align pointers and references
PointerAlignment: Right
# ANGLE likes to align things as much as possible.
AlignOperands: true
AlignConsecutiveAssignments: true
# Use 2 space negative offset for access modifiers
AccessModifierOffset: -2
# TODO(jmadill): Decide if we want this on. Doesn't have an "all or none" mode.
AllowShortCaseLabelsOnASingleLine: false
# Useful for spacing out functions in classes
KeepEmptyLinesAtTheStartOfBlocks: true
# Indent nested PP directives.
IndentPPDirectives: AfterHash
# Include blocks style
IncludeBlocks: Preserve
AttributeMacros:
- OPENTELEMETRY_UNLIKELY
- OPENTELEMETRY_LIKELY
- OPENTELEMETRY_MAYBE_UNUSED
- OPENTELEMETRY_DEPRECATED
- OPENTELEMETRY_API_SINGLETON
- OPENTELEMETRY_LOCAL_SYMBOL
- OPENTELEMETRY_EXPORT
- OPENTELEMETRY_SANITIZER_NO_MEMORY
- OPENTELEMETRY_SANITIZER_NO_THREAD
- OPENTELEMETRY_SANITIZER_NO_ADDRESS

View file

@ -0,0 +1,42 @@
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
Checks: >
-*,
performance-*,
portability-*,
abseil-*,
-abseil-string-find-str-contains,
bugprone-*,
-bugprone-easily-swappable-parameters,
-bugprone-implicit-widening-of-multiplication-result,
-bugprone-inc-dec-in-conditions,
-bugprone-narrowing-conversions,
-bugprone-unchecked-optional-access,
-bugprone-unhandled-exception-at-new,
-bugprone-unused-local-non-trivial-variable,
google-*,
-google-build-using-namespace,
-google-default-arguments,
-google-explicit-constructor,
-google-readability-avoid-underscore-in-googletest-name,
-google-readability-braces-around-statements,
-google-readability-namespace-comments,
-google-readability-todo,
-google-runtime-references,
misc-*,
-misc-const-correctness,
-misc-include-cleaner,
-misc-non-private-member-variables-in-classes,
-misc-unused-alias-decls,
-misc-use-anonymous-namespace,
cppcoreguidelines-*,
-cppcoreguidelines-owning-memory,
-cppcoreguidelines-avoid-do-while,
-cppcoreguidelines-avoid-c-arrays,
-cppcoreguidelines-avoid-magic-numbers,
-cppcoreguidelines-init-variables,
-cppcoreguidelines-macro-usage,
-cppcoreguidelines-non-private-member-variables-in-classes,
-cppcoreguidelines-avoid-non-const-global-variables,
-cppcoreguidelines-pro-*

View file

@ -0,0 +1,7 @@
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
# If comment markup is enabled, don't reflow the first comment block in
# eachlistfile. Use this to preserve formatting of your
# copyright/licensestatements.
first_comment_is_literal = True

View file

@ -0,0 +1,52 @@
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
# Ignore the following directories
./.git/*
./.github/*
./third_party/benchmark/*
./third_party/boost/*
./third_party/googletest/*
./third_party/ms-gsl/*
./third_party/nlohmann-json/*
./third_party/opentelemetry-proto/*
./third_party/prometheus-cpp/*
./tools/vcpkg/*
./tools/ports/*
# Third party code
./api/include/opentelemetry/nostd/internal/absl/*
./exporters/jaeger/thrift-gen/*
./exporters/etw/include/opentelemetry/exporters/etw/TraceLoggingDynamic.h
# Doc
./docs/*
## Ignore the following files patterns
*.md
*.rst
*.png
*.log
*.patch
*.json
*.nuspec
*.pem
# Packaging
*/CONTROL
# LICENSE files
*/LICENSE
# Ignore the following misc files
./.bazelignore
./.bazelversion
./docker/.gitignore
.markdownlintignore
./ci/toc.yml
./ci/valgrind-suppressions

View file

@ -0,0 +1,55 @@
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
FROM ubuntu:24.04@sha256:1e622c5f073b4f6bfad6632f2616c7f59ef256e96fe78bf6a595d1dc4376ac02
RUN apt update && apt install -y \
build-essential \
ca-certificates \
wget \
cmake \
git \
sudo \
nano \
pkg-config \
ninja-build \
clang-format \
clang-tidy \
autoconf \
automake \
libtool \
python3-pip
RUN pip install "conan==2.15.1" --break-system-packages
ARG USER_UID=1000
ARG USER_GID=1000
ARG USER_NAME=devuser
ENV USER_NAME=devuser
ENV USER_UID=${USER_UID}
ENV USER_GID=${USER_GID}
ENV INSTALL_PACKAGES=
ENV IS_CONTAINER_BUILD=true
COPY ./.devcontainer/customize_container.sh /tmp/opentelemetry_cpp/devcontainer/customize_container.sh
RUN /tmp/opentelemetry_cpp/devcontainer/customize_container.sh
USER devuser
RUN conan profile detect --force
ARG CONAN_FILE=conanfile_stable.txt
ARG CONAN_BUILD_TYPE=Debug
ARG CXX_STANDARD=17
WORKDIR /home/devuser/conan
COPY ./install/conan/ .
RUN conan install ./${CONAN_FILE} --build=missing -s build_type=${CONAN_BUILD_TYPE}
ENV CMAKE_TOOLCHAIN_FILE=/home/devuser/conan/build/${CONAN_BUILD_TYPE}/generators/conan_toolchain.cmake
ENV CXX_STANDARD=${CXX_STANDARD}
ENV BUILD_TYPE=${CONAN_BUILD_TYPE}
ENV CONAN_FILE=${CONAN_FILE}
WORKDIR /workspaces/opentelemetry-cpp
ENTRYPOINT []
CMD ["/bin/bash"]

View file

@ -0,0 +1,58 @@
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
FROM otel/cpp_format_tools
ARG USER_UID=1000
ARG USER_GID=1000
ARG INSTALL_PACKAGES=
ARG CXX_STANDARD=17
ARG CMAKE_VERSION=3.31.6
ARG ABSEIL_CPP_VERSION=20230125.3
ARG PROTOBUF_VERSION=23.3
ARG GRPC_VERSION=v1.55.0
ENV CXX_STANDARD=${CXX_STANDARD}
ENV CMAKE_VERSION=${CMAKE_VERSION}
ENV ABSEIL_CPP_VERSION=${ABSEIL_CPP_VERSION}
ENV PROTOBUF_VERSION=${PROTOBUF_VERSION}
ENV GRPC_VERSION=${GRPC_VERSION}
COPY ci /opt/ci
RUN apt update && apt install -y wget \
ninja-build \
libcurl4-openssl-dev \
clang-tidy \
shellcheck
RUN cd /opt/ci && bash setup_cmake.sh
RUN cd /opt/ci && bash setup_ci_environment.sh
RUN cd /opt && bash ci/setup_googletest.sh \
&& bash ci/install_abseil.sh \
&& bash ci/install_protobuf.sh \
&& bash ci/setup_grpc.sh -r $GRPC_VERSION -s $CXX_STANDARD -p protobuf -p abseil-cpp
ADD https://github.com/bazelbuild/bazelisk/releases/download/v1.22.1/bazelisk-linux-amd64 /usr/local/bin
RUN git config --global core.autocrlf input \
&& chmod +x /usr/local/bin/bazelisk-linux-amd64
ENV INSTALL_PACKAGES=${INSTALL_PACKAGES}
ENV USER_NAME=devuser
ENV USER_UID=${USER_UID}
ENV USER_GID=${USER_GID}
ENV IS_CONTAINER_BUILD=true
COPY ./.devcontainer/customize_container.sh /tmp/opentelemetry_cpp/devcontainer/customize_container.sh
RUN /tmp/opentelemetry_cpp/devcontainer/customize_container.sh
RUN apt install -y npm && npm install -g markdownlint-cli@0.44.0
USER devuser
WORKDIR /workspaces/opentelemetry-cpp
ENTRYPOINT []
CMD ["/bin/bash"]

View file

@ -0,0 +1,65 @@
# Customizing Your Dev Container
Customize your dev container using build arguments (for direct Docker builds) or
environment variables (for evaluation in `devcontainer.json`).
* **CMake version:**
The version of cmake to install. (Default: 3.31.6)
* Docker ARG:
`CMAKE_VERSION`
* Host Environment Variable:
`OTEL_CPP_DEVCONTAINER_CMAKE_VERSION`
* **CXX standard:**
This is the C++ standard to build from (eg: 17, 20, ...). (Default: 17)
* Docker ARG:
`CXX_STANDARD`
* Host Environment Variable:
`OTEL_CPP_DEVCONTAINER_CXX_STANDARD`
* **abseil-cpp version:**
This is the version of abseil-cpp that will be used to build protobuf, gRPC,
and opentelemetry-cpp.
* Docker ARG:
`ABSEIL_CPP_VERSION`
* Host Environment Variable:
`OTEL_CPP_DEVCONTAINER_ABSEIL_CPP_VERSION`
* **Protobuf version:**
* Docker ARG:
`PROTOBUF_VERSION`
* Host Environment Variable:
`OTEL_CPP_DEVCONTAINER_PROTOBUF_VERSION`
* **gRPC version:**
* Docker ARG:
`GRPC_VERSION`
* Host Environment Variable:
`OTEL_CPP_DEVCONTAINER_GRPC_VERSION`
* **User ID (UID):**
User ID (Default: `1000`)
* Docker ARG:
`USER_UID`
* Host Environment Variable:
`OTEL_CPP_DEVCONTAINER_USER_UID`
* **Group ID (GID):**
User group ID (Default: `1000`)
* Docker ARG:
`USER_GID`
* Host Environment Variable:
`OTEL_CPP_DEVCONTAINER_USER_GID`
* **Install Packages:**
These are the additional packages that will be installed via `apt install` in the devcontainer. This is a space separated list.
* Docker ARG:
`INSTALL_PACKAGES` (Default: ``)
* Host Environment Variable:
`OTEL_CPP_DEVCONTAINER_INSTALL_PACKAGES` (Default: ``)
## Examples
* `docker build --build-arg CXX_STANDARD="20" --build-arg INSTALL_PACKAGES="nano gitk"...`
* `export OTEL_CPP_DEVCONTAINER_CXX_STANDARD=20`
* `export OTEL_CPP_DEVCONTAINER_INSTALL_PACKAGES="nano gitk"`

View file

@ -0,0 +1,39 @@
#!/bin/bash
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
set -eu
if [[ $IS_CONTAINER_BUILD != "true" ]]; then
echo "This script should only run inside a Docker container."
exit 1
fi
if [[ -n "$INSTALL_PACKAGES" ]]; then
packages=($INSTALL_PACKAGES)
for package in "${packages[@]}"; do
apt install -y "$package"
done
fi
if [[ $(id "$USER_NAME" 2>/dev/null) ]]; then
echo "User '$USER_NAME' already exists. Removing it."
userdel -rf "$USER_NAME"
elif [[ $(id -u "$USER_UID" 2>/dev/null) ]]; then
OTHER_USER=$(getent passwd "$USER_UID" | cut -d: -f1)
echo "User '$OTHER_USER' exists with UID $USER_UID. Removing it."
userdel -rf "$OTHER_USER"
fi
if [[ ! $(getent group "$USER_GID" 2>/dev/null) ]]; then
echo "Group '$USER_GID' does not exist. Adding it."
groupadd -g "$USER_GID" "$USER_NAME"
fi
useradd -m -u "$USER_UID" -g "$USER_GID" -s /bin/bash "$USER_NAME"
echo "Created user '$USER_NAME' (UID: $USER_UID, GID: $USER_GID)."
echo "$USER_NAME ALL=(ALL) NOPASSWD:ALL" | tee /etc/sudoers.d/"$USER_NAME"
echo "User and group setup complete."

View file

@ -0,0 +1,35 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.162.0/containers/javascript-node
{
"name": "opentelemetry-cpp",
"build": {
"context": "..",
"dockerfile": "Dockerfile.dev",
"args": {
"USER_UID": "${localEnv:OTEL_CPP_DEVCONTAINER_USER_UID:1000}",
"USER_GID": "${localEnv:OTEL_CPP_DEVCONTAINER_USER_GID:1000}",
"INSTALL_PACKAGES": "${localEnv:OTEL_CPP_DEVCONTAINER_INSTALL_PACKAGES:}",
"CMAKE_VERSION": "${localEnv:OTEL_CPP_DEVCONTAINER_CMAKE_VERSION:3.31.6}",
"CXX_STANDARD": "${localEnv:OTEL_CPP_DEVCONTAINER_CXX_STANDARD:17}",
"GRPC_VERSION": "${localEnv:OTEL_CPP_DEVCONTAINER_GRPC_VERSION:v1.55.0}",
"PROTOBUF_VERSION": "${localEnv:OTEL_CPP_DEVCONTAINER_PROTOBUF_VERSION:23.3}",
"ABSEIL_CPP_VERSION":"${localEnv:OTEL_CPP_DEVCONTAINER_ABSEIL_CPP_VERSION:20230125.3}"
}
},
"customizations": {
"vscode": {
"extensions": [
"ms-vscode.cpptools",
"ms-azuretools.vscode-docker",
"ms-vscode.cpptools-extension-pack"
],
"settings": {
"terminal.integrated.shell.linux": "/bin/bash",
}
}
},
"remoteUser": "devuser"
}

View file

@ -0,0 +1,47 @@
##### Source code #####
## C++ and C source files
*.c text eol=lf diff=cpp
*.h text eol=lf diff=cpp
*.cc text eol=lf diff=cpp
*.cpp text eol=lf diff=cpp
*.cxx text eol=lf diff=cpp
*.hpp text eol=lf diff=cpp
## Python scripts
*.py text eol=lf diff=python
## Perl scripts/libraries/modules
*.perl text eol=lf diff=perl
*.pl text eol=lf diff=perl
*.pm text eol=lf diff=perl
## Shell scripts
*.sh text eol=lf
*.bash text eol=lf
## Windows batch and PowerShell scripts
*.bat text eol=crlf
*.cmd text eol=crlf
*.ps1 text eol=crlf
##### Other file types #####
## Text files and documentation
*.txt text
README* text
INSTALL* text
LICENSE* text
## Non-text documentation
*.html text diff=html
*.pdf binary
*.rtf binary
## git files
.gitignore text eol=lf
.gitattributes text eol=lf
## bazel files
WORKSPACE text eol=lf
BUILD text eol=lf

View file

@ -0,0 +1,50 @@
codecov:
require_ci_to_pass: false
max_report_age: off
coverage:
precision: 2
round: up
range: "80...100"
status:
project:
default:
informational: true
target: auto
threshold: 10%
patch: false
parsers:
gcov:
branch_detection:
conditional: yes
loop: yes
method: no
macro: no
comment:
layout: "reach,diff,flags,tree"
behavior: default
require_changes: false
# Relative file path fixing.
# CI file paths must match Git file paths.
# This fix removes the "/home/runner/" prefix
# to coverage report file paths.
fixes:
- "/home/runner/::"
ignore:
- "docs/**/*"
- "docker/**/*"
- "examples/**/*"
- "bazel/**/*"
- "cmake/**/*"
- "buildscripts/**/*"
- "third_party/**/*"
- "test_common/**/*"
- "tools/**/*"
- ".vscode/**/*"
- ".github/**/*"
- "**/test/**/*"
- "**.md"

View file

@ -0,0 +1,8 @@
# Code owners file.
# This file controls who is tagged for review for any given pull request.
# For ETW exporter
exporters/etw/* @reyang @maxgolov @lalitb @ThomsonTan @open-telemetry/cpp-approvers
# For anything not explicitly taken by someone else:
* @open-telemetry/cpp-approvers

View file

@ -0,0 +1,19 @@
---
name: Bug Report
about: Create a report to help us improve
labels: bug
---
**Describe your environment** Describe any aspect of your environment relevant to the problem, including your platform, build system, version numbers of installed dependencies, etc. If you're reporting a problem with a specific version of a library in this repo, please check whether the problem has been fixed on main branch.
**Steps to reproduce**
Describe exactly how to reproduce the error. Include a code sample if applicable.
**What is the expected behavior?**
What did you expect to see?
**What is the actual behavior?**
What did you see instead?
**Additional context**
Add any other context about the problem here.

View file

@ -0,0 +1,19 @@
---
name: Feature Request
about: Suggest an idea for this project
labels: feature-request
---
Before opening a feature request against this repo, consider whether the feature should/could be implemented in the [other OpenTelemetry client libraries](https://github.com/open-telemetry/). If so, please [open an issue on opentelemetry-specification](https://github.com/open-telemetry/opentelemetry-specification/issues/new) first.
**Is your feature request related to a problem?**
If so, provide a concise description of the problem.
**Describe the solution you'd like**
What do you want to happen instead? What is the expected behavior?
**Describe alternatives you've considered**
Which alternative solutions or features have you considered?
**Additional context**
Add any other context about the feature request here.

View file

@ -0,0 +1,13 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
labels:
- "GHA"
- package-ecosystem: "devcontainers"
directory: "/"
schedule:
interval: daily

View file

@ -0,0 +1,11 @@
Fixes # (issue)
## Changes
Please provide a brief description of the changes here.
For significant contributions please make sure you have completed the following items:
* [ ] `CHANGELOG.md` updated for non-trivial changes
* [ ] Unit tests have been added
* [ ] Changes in public API reviewed

View file

@ -0,0 +1,38 @@
# Process
This file documents local admin changes for opentelemetry-cpp,
per the community process: https://github.com/open-telemetry/community/blob/main/docs/how-to-configure-new-repository.md
Please note that the EasyCLA check **MUST** stay **REQUIRED**,
it should never be disabled or bypassed, at the risk of tainting the repository.
# Guidelines
The best is to open a PR first that describes the change,
so it can be discussed during review (maybe it is not needed,
maybe there is an alternate solution, ...).
The PR must add a log entry in this file, detailing:
* the date the change is implemented
* what is changed exactly (which setting)
* a short rationale
Admin changes are then applied only when the PR is merged.
If for some reason a change is implemented in emergency,
before a PR can be discussed and merged,
a PR should still be prepared and pushed after the fact to
describe the settings changed.
# Log of local changes
## 2023-11-03
Created log file `.github/repository-settings.md`, since admin permissions are now granted to maintainers.
See https://github.com/open-telemetry/community/issues/1727
No setting changed.

View file

@ -0,0 +1,82 @@
name: OpenTelemetry-cpp benchmarks
on:
push:
branches:
- main
permissions:
contents: write
deployments: write
jobs:
benchmark:
name: Run OpenTelemetry-cpp benchmarks
runs-on: ubuntu-latest
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
with:
egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: 'recursive'
- name: Mount Bazel Cache
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
env:
cache-name: bazel_cache
with:
path: /home/runner/.cache/bazel
key: bazel_benchmark
- name: setup
run: |
sudo ./ci/setup_ci_environment.sh
sudo ./ci/install_bazelisk.sh
- name: Run benchmark
id: run_benchmarks
run: |
./ci/do_ci.sh bazel.benchmark
mkdir -p benchmarks
mv api-benchmark_result.json benchmarks
mv sdk-benchmark_result.json benchmarks
mv exporters-benchmark_result.json benchmarks
- uses: actions/upload-artifact@6027e3dd177782cd8ab9af838c04fd81a07f1d47 # main March 2025
with:
name: benchmark_results
path: benchmarks
store_benchmark:
needs: benchmark
strategy:
matrix:
components: ["api", "sdk", "exporters"]
name: Store benchmark result
runs-on: ubuntu-latest
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
with:
egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # main March 2025
with:
name: benchmark_results
path: benchmarks
- name: Print json files
id: print_json
run: |
cat benchmarks/*
- name: Push benchmark result
uses: benchmark-action/github-action-benchmark@d48d326b4ca9ba73ca0cd0d59f108f9e02a381c7 # v1.20.4
with:
name: OpenTelemetry-cpp ${{ matrix.components }} Benchmark
tool: 'googlecpp'
output-file-path: benchmarks/${{ matrix.components }}-benchmark_result.json
github-token: ${{ secrets.GITHUB_TOKEN }}
auto-push: true
# Show alert with commit comment on detecting possible performance regression
alert-threshold: '200%'
comment-on-alert: true
fail-on-alert: false
gh-pages-branch: gh-pages
benchmark-data-dir-path: benchmarks

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,89 @@
name: clang-tidy
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
contents: read
jobs:
clang-tidy:
runs-on: ubuntu-24.04
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
with:
egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: recursive
- name: Setup Environment
env:
PROTOBUF_VERSION: '23.3'
ABSEIL_CPP_VERSION: '20230125.3'
CXX_STANDARD: '14'
run: |
sudo apt update -y
sudo apt install -y --no-install-recommends --no-install-suggests \
build-essential \
iwyu \
cmake \
libssl-dev \
libcurl4-openssl-dev \
libprotobuf-dev \
protobuf-compiler \
libgmock-dev \
libgtest-dev \
libbenchmark-dev
if ! command -v clang-tidy &> /dev/null; then
echo "clang-tidy could not be found"
exit 1
fi
echo "Using clang-tidy version: $(clang-tidy --version)"
echo "clang-tidy installed at: $(which clang-tidy)"
- name: Prepare CMake
env:
CC: clang
CXX: clang++
run: |
echo "Running cmake..."
cmake -B build \
-DCMAKE_CXX_STANDARD=14 \
-DWITH_STL=CXX14 \
-DWITH_OTLP_HTTP=ON \
-DWITH_OTLP_FILE=ON \
-DWITH_PROMETHEUS=ON \
-DWITH_ZIPKIN=ON \
-DWITH_ELASTICSEARCH=ON \
-DWITH_OTLP_HTTP_COMPRESSION=ON \
-DWITH_EXAMPLES=ON \
-DWITH_EXAMPLES_HTTP=ON \
-DBUILD_W3CTRACECONTEXT_TEST=ON \
-DWITH_METRICS_EXEMPLAR_PREVIEW=ON \
-DWITH_ASYNC_EXPORT_PREVIEW=ON \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
- name: Run clang-tidy
run: |
cmake --build build --target opentelemetry_proto
jq -r .[].file build/compile_commands.json | grep -vE '/(generated|third_party)/' | xargs -P $(nproc) -n 1 clang-tidy --quiet -p build 2>&1 | tee -a clang-tidy.log
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: Logs (clang-tidy)
path: ./clang-tidy.log
- name: Count warnings
run: |
COUNT=$(grep -c "warning:" clang-tidy.log)
echo "clang-tidy reported ${COUNT} warning(s)"
# TODO: include WITH_OTLP_GRPC flags.

View file

@ -0,0 +1,372 @@
name: CMake Install Tests
on:
workflow_dispatch:
push:
branches: [ main ]
pull_request:
branches: [ main ]
permissions:
contents: read
jobs:
windows_2022_vcpkg_submodule:
name: Windows 2022 vcpkg submodule versions cxx17 (static libs - dll)
runs-on: windows-2022
env:
# Set to the latest version of cmake 3.x
CMAKE_VERSION: '3.31.6'
# cxx17 is the default for windows-2022
CXX_STANDARD: '17'
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
with:
egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: 'recursive'
- name: Build dependencies with vcpkg submodule
run: |
./ci/setup_cmake.ps1
./ci/setup_windows_ci_environment.ps1
- name: Run Tests
run: ./ci/do_ci.ps1 cmake.install.test
- name: Run DLL Tests
run: ./ci/do_ci.ps1 cmake.dll.install.test
windows_2019_vcpkg_submodule_min_cmake:
name: Windows 2019 vcpkg submodule versions minimum cmake cxx14 (static libs)
runs-on: windows-2019
env:
# cmake 3.15 is the minimum for windows builds (See https://github.com/open-telemetry/opentelemetry-cpp/pull/3349#discussion_r2030319430)
CMAKE_VERSION: '3.15.0'
# cxx14 is the default for windows-2019
CXX_STANDARD: '14'
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
with:
egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: 'recursive'
- name: Build dependencies with vcpkg submodule
run: |
./ci/setup_cmake.ps1
./ci/setup_windows_ci_environment.ps1
- name: Run Tests
run: ./ci/do_ci.ps1 cmake.install.test
ubuntu_2404_system_packages:
name: Ubuntu 24.04 apt packages cxx17 (static libs - shared libs)
runs-on: ubuntu-24.04
env:
INSTALL_TEST_DIR: '/home/runner/install_test'
# CMake 3.28 is apt package version for Ubuntu 24.04
CMAKE_VERSION: '3.28.3'
# cxx17 is the default for Ubuntu 24.04
CXX_STANDARD: '17'
BUILD_TYPE: 'Debug'
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
with:
egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: 'recursive'
- name: Install libcurl, zlib, nlohmann-json with apt
run: |
sudo -E ./ci/setup_ci_environment.sh
sudo -E ./ci/setup_cmake.sh
sudo -E ./ci/setup_googletest.sh
- name: Install abseil, protobuf, and grpc with apt
run: |
sudo -E apt-get update
sudo -E apt-get install -y libabsl-dev libprotobuf-dev libgrpc++-dev protobuf-compiler protobuf-compiler-grpc
- name: Run Tests (static libs)
env:
BUILD_SHARED_LIBS: 'OFF'
run: ./ci/do_ci.sh cmake.install.test
- name: Run Tests (shared libs)
env:
BUILD_SHARED_LIBS: 'ON'
run: ./ci/do_ci.sh cmake.install.test
ubuntu_2404_latest:
name: Ubuntu 24.04 latest versions cxx20 (static libs)
runs-on: ubuntu-24.04
env:
INSTALL_TEST_DIR: '/home/runner/install_test'
# Set to the latest version of cmake 3.x
CMAKE_VERSION: '3.31.6'
# Set to the latest cxx standard supported by opentelemetry-cpp
CXX_STANDARD: '20'
# Versions below set to the latest version available
# The abseil and protobuf versions are taken from
# the grpc submodules at the GRPC_VERSION tag
GOOGLETEST_VERSION: '1.16.0'
ABSEIL_CPP_VERSION: '20240722.1'
PROTOBUF_VERSION: '29.0'
GRPC_VERSION: 'v1.71.0'
BUILD_TYPE: 'Debug'
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
with:
egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: 'recursive'
- name: Install gtest, libcurl, zlib, nlohmann-json with apt
run: |
sudo -E ./ci/setup_ci_environment.sh
sudo -E ./ci/setup_cmake.sh
sudo -E ./ci/setup_googletest.sh
- name: Build abseil, protobuf, and grpc with ci scripts
run: |
sudo -E ./ci/install_abseil.sh
sudo -E ./ci/install_protobuf.sh
sudo -E ./ci/setup_grpc.sh -r $GRPC_VERSION -s $CXX_STANDARD -p protobuf -p abseil-cpp
- name: Run Tests (static libs)
env:
BUILD_SHARED_LIBS: 'OFF'
run: ./ci/do_ci.sh cmake.install.test
ubuntu_2204_stable:
name: Ubuntu 22.04 stable versions cxx17 (static libs - shared libs)
runs-on: ubuntu-22.04
env:
INSTALL_TEST_DIR: '/home/runner/install_test'
# CMake 3.22 is the apt package version for Ubuntu 22.04
CMAKE_VERSION: '3.22.0'
CXX_STANDARD: '17'
# These are stable versions tested in the main ci workflow
# and defaults in the devcontainer
GOOGLETEST_VERSION: '1.14.0'
ABSEIL_CPP_VERSION: '20230125.3'
PROTOBUF_VERSION: '23.3'
GRPC_VERSION: 'v1.55.0'
BUILD_TYPE: 'Debug'
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
with:
egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: 'recursive'
- name: Install gtest, libcurl, zlib, nlohmann-json with apt
run: |
sudo -E ./ci/setup_ci_environment.sh
sudo -E ./ci/setup_cmake.sh
sudo -E ./ci/setup_googletest.sh
- name: Build abseil, protobuf, and grpc with ci scripts
run: |
sudo -E ./ci/install_abseil.sh
sudo -E ./ci/install_protobuf.sh
sudo -E ./ci/setup_grpc.sh -r $GRPC_VERSION -s $CXX_STANDARD -p protobuf -p abseil-cpp
- name: Run Tests (static libs)
env:
BUILD_SHARED_LIBS: 'OFF'
run: ./ci/do_ci.sh cmake.install.test
- name: Run Tests (shared libs)
env:
BUILD_SHARED_LIBS: 'ON'
run: ./ci/do_ci.sh cmake.install.test
ubuntu_2204_minimum:
name: Ubuntu 22.04 minimum versions cxx14 (static libs - shared libs)
runs-on: ubuntu-22.04
env:
INSTALL_TEST_DIR: '/home/runner/install_test'
# Set to the current minimum version of cmake
CMAKE_VERSION: '3.14.0'
# cxx14 is the default for Ubuntu 22.04
CXX_STANDARD: '14'
# This is the apt package version of googletest for Ubuntu 22.04
GOOGLETEST_VERSION: '1.11.0'
# These are minimum versions tested in the main ci workflow
ABSEIL_CPP_VERSION: '20220623.2'
PROTOBUF_VERSION: '21.12'
GRPC_VERSION: 'v1.49.2'
BUILD_TYPE: 'Debug'
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
with:
egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: 'recursive'
- name: Install gtest, libcurl, zlib, nlohmann-json with apt
run: |
sudo -E ./ci/setup_ci_environment.sh
sudo -E ./ci/setup_cmake.sh
sudo -E ./ci/setup_googletest.sh
- name: Build abseil, protobuf, and grpc with ci scripts
run: |
sudo -E ./ci/install_abseil.sh
sudo -E ./ci/install_protobuf.sh
sudo -E ./ci/setup_grpc.sh -r $GRPC_VERSION -s $CXX_STANDARD -p protobuf -p abseil-cpp
- name: Run Tests (static libs)
env:
BUILD_SHARED_LIBS: 'OFF'
run: ./ci/do_ci.sh cmake.install.test
- name: Run Tests (shared libs)
env:
BUILD_SHARED_LIBS: 'ON'
run: ./ci/do_ci.sh cmake.install.test
ubuntu_2404_conan_stable:
name: Ubuntu 24.04 conan stable versions cxx17 (static libs - shared libs - opentracing shim)
runs-on: ubuntu-24.04
env:
INSTALL_TEST_DIR: '/home/runner/install_test'
# CMake 3.28 is apt package version for Ubuntu 24.04
CMAKE_VERSION: '3.28.3'
CXX_STANDARD: '17'
CMAKE_TOOLCHAIN_FILE: /home/runner/conan/build/Debug/generators/conan_toolchain.cmake
BUILD_TYPE: 'Debug'
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
with:
egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: 'recursive'
- name: Install Conan
run: |
python3 -m pip install pip==25.0.1
pip install "conan==2.15.1"
conan profile detect --force
- name: Install or build all dependencies with Conan
run: |
sudo -E ./ci/setup_cmake.sh
conan install install/conan/conanfile_stable.txt --build=missing -of /home/runner/conan -s build_type=${BUILD_TYPE} -s compiler.cppstd=${CXX_STANDARD}
- name: Run Tests (static libs)
env:
BUILD_SHARED_LIBS: 'OFF'
run: ./ci/do_ci.sh cmake.install.test
- name: Run Tests (shared libs)
env:
BUILD_SHARED_LIBS: 'ON'
run: ./ci/do_ci.sh cmake.install.test
- name: verify pkgconfig packages
run: |
export PKG_CONFIG_PATH=$INSTALL_TEST_DIR/lib/pkgconfig:$PKG_CONFIG_PATH
./ci/verify_packages.sh
- name: Run OpenTracing Shim Test
run: ./ci/do_ci.sh cmake.opentracing_shim.install.test
ubuntu_2404_conan_latest:
name: Ubuntu 24.04 conan latest versions cxx17 (static libs)
runs-on: ubuntu-24.04
env:
INSTALL_TEST_DIR: '/home/runner/install_test'
# Set to the latest version of cmake 3.x
CMAKE_VERSION: '3.31.6'
CXX_STANDARD: '17'
CMAKE_TOOLCHAIN_FILE: /home/runner/conan/build/Debug/generators/conan_toolchain.cmake
BUILD_TYPE: 'Debug'
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
with:
egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: 'recursive'
- name: Install Conan
run: |
python3 -m pip install pip==25.0.1
pip install "conan==2.15.1"
conan profile detect --force
- name: Install or build all dependencies with Conan
run: |
sudo -E ./ci/setup_cmake.sh
conan install install/conan/conanfile_latest.txt --build=missing -of /home/runner/conan -s build_type=${BUILD_TYPE} -s compiler.cppstd=${CXX_STANDARD}
- name: Run Tests (static libs)
env:
BUILD_SHARED_LIBS: 'OFF'
run: ./ci/do_ci.sh cmake.install.test
- name: verify pkgconfig packages
run: |
export PKG_CONFIG_PATH=$INSTALL_TEST_DIR/lib/pkgconfig:$PKG_CONFIG_PATH
./ci/verify_packages.sh
macos_14_conan_stable:
name: macOS 14 conan stable versions cxx17 (static libs)
runs-on: macos-14
env:
INSTALL_TEST_DIR: '/Users/runner/install_test'
CMAKE_VERSION: '3.28.3'
CXX_STANDARD: '17'
CMAKE_TOOLCHAIN_FILE: '/Users/runner/conan/build/Debug/generators/conan_toolchain.cmake'
BUILD_TYPE: 'Debug'
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
with:
egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: 'recursive'
- name: Install Conan and tools
run: |
brew install conan autoconf automake libtool coreutils
./ci/setup_cmake_macos.sh
conan profile detect --force
- name: Install or build all dependencies with Conan
run: conan install install/conan/conanfile_stable.txt --build=missing -of /Users/runner/conan -s build_type=${BUILD_TYPE} -s compiler.cppstd=${CXX_STANDARD}
- name: Run Tests (static libs)
env:
BUILD_SHARED_LIBS: 'OFF'
run: ./ci/do_ci.sh cmake.install.test
macos_14_brew_packages:
name: macOS 14 brew latest versions cxx17 (static libs)
runs-on: macos-14
env:
INSTALL_TEST_DIR: '/Users/runner/install_test'
# Set to the latest version of cmake 3.x
CMAKE_VERSION: '3.31.6'
CXX_STANDARD: '17'
BUILD_TYPE: 'Debug'
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
with:
egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: 'recursive'
- name: Install Dependencies with Homebrew
run: |
./ci/setup_cmake_macos.sh
brew install coreutils
brew install googletest
brew install google-benchmark
brew install zlib
brew install abseil
brew install protobuf
brew install grpc
brew install nlohmann-json
brew install prometheus-cpp
- name: Run Tests (static libs)
env:
BUILD_SHARED_LIBS: 'OFF'
run: ./ci/do_ci.sh cmake.install.test

View file

@ -0,0 +1,48 @@
name: "CodeQL"
on:
push:
branches: [main]
pull_request:
# The branches below must be a subset of the branches above
branches: [main]
permissions:
contents: read
jobs:
CodeQL-Build:
permissions:
actions: read # for github/codeql-action/init to get workflow details
contents: read # for actions/checkout to fetch code
security-events: write # for github/codeql-action/autobuild to send a status report
runs-on: ubuntu-latest
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
with:
egress-policy: audit
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: 'recursive'
- name: Remove Third_party Modules from Code Scan
run: |
rm -rf third_party
- name: Setup
env:
CC: /usr/bin/gcc-12
CXX: /usr/bin/g++-12
GOOGLETEST_VERSION: 1.12.1
run: |
sudo -E ./ci/setup_googletest.sh
sudo -E ./ci/setup_ci_environment.sh
- name: Initialize CodeQL
uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
with:
languages: cpp
- name: Autobuild
uses: github/codeql-action/autobuild@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18

View file

@ -0,0 +1,77 @@
name: cppcheck
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
permissions:
contents: read
jobs:
cppcheck:
runs-on: ubuntu-24.04
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
with:
egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: 'recursive'
- name: Set up dependencies
run: |
sudo apt update -y
sudo apt install -y cppcheck
- name: Run cppcheck
run: |
cppcheck --version | tee cppcheck.log
cppcheck \
--force \
--enable=warning,performance,portability \
--inline-suppr \
--suppress=unknownMacro:exporters/etw/include/opentelemetry/exporters/etw/TraceLoggingDynamic.h \
--language=c++ \
--std=c++14 \
-I api/include \
-I exporters/elasticsearch/include \
-I exporters/etw/include \
-I exporters/memory/include \
-I exporters/ostream/include \
-I exporters/otlp/include \
-I exporters/prometheus/include \
-I exporters/zipkin/include \
-I ext/include \
-I opentracing-shim/include \
-I sdk/include \
-i build \
-i test \
-i third_party \
-j $(nproc) \
. 2>&1 | tee --append cppcheck.log
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
if: success() || failure()
with:
name: Logs (cppcheck)
path: ./cppcheck.log
- name: Count warnings
run: |
set +e
readonly WARNING_COUNT=`grep -c -E "\[.+\]" cppcheck.log`
echo "cppcheck reported ${WARNING_COUNT} warning(s)"
# Acceptable limit, to decrease over time down to 0
readonly WARNING_LIMIT=10
# FAIL the build if WARNING_COUNT > WARNING_LIMIT
if [ $WARNING_COUNT -gt $WARNING_LIMIT ] ; then
exit 1
# WARN in annotations if WARNING_COUNT > 0
elif [ $WARNING_COUNT -gt 0 ] ; then
echo "::warning::cppcheck reported ${WARNING_COUNT} warning(s)"
fi

View file

@ -0,0 +1,54 @@
name: 'OpenTelemetry-cpp dependencies image'
on:
schedule:
- cron: "0 3 * * 6"
permissions:
contents: read
jobs:
docker_image:
name: Docker Image
runs-on: ubuntu-latest
timeout-minutes: 300
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
with:
egress-policy: audit
-
name: checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
-
name: Set up QEMU
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
-
name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
-
name: Build Image
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with:
builder: ${{ steps.buildx.outputs.name }}
context: ci/
file: ./docker/Dockerfile
build-args: BASE_IMAGE=ubuntu:latest
platforms: linux/amd64
# platforms: linux/amd64,linux/arm64
push: false
tags: otel-cpp-deps
load: true
-
name: Save Image
run: |
docker images
docker save -o /opt/otel-cpp-deps-debian.tar otel-cpp-deps
-
name: Upload Image
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: otel-cpp-deps
path: /opt/otel-cpp-deps-debian.tar
retention-days: 14

View file

@ -0,0 +1,25 @@
name: FOSSA scanning
on:
push:
branches:
- main
permissions:
contents: read
jobs:
fossa:
runs-on: ubuntu-latest
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
with:
egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: fossas/fossa-action@3ebcea1862c6ffbd5cf1b4d0bd6b3fe7bd6f2cac # v1.7.0
with:
api-key: ${{secrets.FOSSA_API_KEY}}
team: OpenTelemetry

View file

@ -0,0 +1,92 @@
name: include-what-you-use
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
permissions:
contents: read
jobs:
iwyu:
runs-on: ubuntu-latest
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
with:
egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: 'recursive'
- name: setup dependencies
run: |
sudo apt update -y
sudo apt install -y --no-install-recommends --no-install-suggests \
build-essential \
iwyu \
ninja-build \
libssl-dev \
libcurl4-openssl-dev \
libprotobuf-dev \
protobuf-compiler \
libgmock-dev \
libgtest-dev \
libbenchmark-dev
sudo ./ci/setup_cmake.sh
- name: setup grpc
run: |
sudo ./ci/setup_grpc.sh
- name: Prepare CMake
run: |
TOPDIR=`pwd`
mkdir build && cd build
CC="clang" CXX="clang++" cmake \
-DCMAKE_CXX_STANDARD=14 \
-DWITH_STL=CXX14 \
-DCMAKE_CXX_INCLUDE_WHAT_YOU_USE="include-what-you-use;-w;-Xiwyu;--mapping_file=${TOPDIR}/.iwyu.imp;" \
-DBUILD_TESTING=ON \
-DBUILD_W3CTRACECONTEXT_TEST=ON \
-DWITH_OTLP_GRPC=ON \
-DWITH_OTLP_HTTP=ON \
-DWITH_OTLP_FILE=ON \
-DWITH_OPENTRACING=ON \
-DWITH_OTLP_HTTP_COMPRESSION=ON \
-DWITH_THREAD_INSTRUMENTATION=ON \
-DWITH_ZIPKIN=ON \
-DWITH_PROMETHEUS=ON \
..
- name: iwyu_tool
run: |
cd build
make -k 2>&1 | tee -a iwyu.log
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
if: success() || failure()
with:
name: Logs (include-what-you-use)
path: ./build/*.log
- name: count warnings
run: |
set +e
cd build
readonly WARNING_COUNT=`grep -c "include-what-you-use reported diagnostics:" iwyu.log`
echo "include-what-you-use reported ${WARNING_COUNT} warning(s)"
# Acceptable limit, to decrease over time down to 0
readonly WARNING_LIMIT=0
# FAIL the build if WARNING_COUNT > WARNING_LIMIT
if [ $WARNING_COUNT -gt $WARNING_LIMIT ] ; then
exit 1
# WARN in annotations if WARNING_COUNT > 0
elif [ $WARNING_COUNT -gt 0 ] ; then
echo "::warning::include-what-you-use reported ${WARNING_COUNT} warning(s)"
fi

View file

@ -0,0 +1,52 @@
name: OSSF Scorecard
on:
push:
branches:
- main
schedule:
- cron: "56 23 * * 6" # once a week
workflow_dispatch:
permissions: read-all
jobs:
analysis:
runs-on: ubuntu-latest
permissions:
# Needed for Code scanning upload
security-events: write
# Needed for GitHub OIDC token if publish_results is true
id-token: write
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
with:
egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1
with:
results_file: results.sarif
results_format: sarif
publish_results: true
# Upload the results as artifacts (optional). Commenting out will disable
# uploads of run results in SARIF format to the repository Actions tab.
# https://docs.github.com/en/actions/advanced-guides/storing-workflow-data-as-artifacts
- name: "Upload artifact"
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: SARIF file
path: results.sarif
retention-days: 5
# Upload the results to GitHub's code scanning dashboard (optional).
# Commenting out will disable upload of results to your repo's Code Scanning dashboard
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
with:
sarif_file: results.sarif

View file

@ -0,0 +1,28 @@
name: Add comment
on:
issues:
types:
- labeled
permissions:
contents: read
jobs:
add-comment:
if: github.event.label.name == 'help wanted'
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
with:
egress-policy: audit
- name: Add comment
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043
with:
issue-number: ${{ github.event.issue.number }}
body: |
This issue is available for anyone to work on. **Make sure to reference this issue in your pull request.**
:sparkles: Thank you for your contribution! :sparkles:

View file

@ -0,0 +1,29 @@
name: OpenTelemetry-cpp project
on:
issues:
types:
- reopened
- opened
permissions:
contents: read
jobs:
label_issues:
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
with:
egress-policy: audit
- uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
github.rest.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ["needs-triage"]
})

View file

@ -0,0 +1,21 @@
name: "Mark stale issues"
on:
schedule:
- cron: "30 1 * * *"
permissions:
contents: read
jobs:
stale:
permissions:
issues: write # for actions/stale to close stale issues
pull-requests: write # for actions/stale to close stale PRs
runs-on: ubuntu-latest
steps:
- uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0
with:
stale-issue-message: "This issue was marked as stale due to lack of activity."
days-before-issue-stale: 60
days-before-close: -1
exempt-issue-labels: "do-not-stale"

84
ext/opentelemetry-cpp-1.21.0/.gitignore vendored Normal file
View file

@ -0,0 +1,84 @@
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
# Ref. https://github.com/github/gitignore/blob/master/C%2B%2B.gitignore
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
*.pdb
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
# Bazel files
MODULE.bazel.lock
/bazel-*
# Mac
.DS_Store
# Output directories
/out
/out.*
# Indicator that the tools were deployed
.buildtools
# Temporary Bazel directories
/bazel-*
/plugin
/build
tags
.cache/clangd/*
# Temporary dir used when generating semconv
buildscripts/semantic-convention/tmp-semconv/
# Generated cert keys in functional tests
functional/cert/ca.csr
functional/cert/ca.pem
functional/cert/ca-key.pem
functional/cert/client_cert.csr
functional/cert/client_cert.pem
functional/cert/client_cert-key.pem
functional/cert/server_cert.csr
functional/cert/server_cert.pem
functional/cert/server_cert-key.pem
functional/cert/ca_b.csr
functional/cert/ca_b.pem
functional/cert/ca_b-key.pem
functional/cert/client_cert_b.csr
functional/cert/client_cert_b.pem
functional/cert/client_cert_b-key.pem
functional/cert/server_cert_b.csr
functional/cert/server_cert_b.pem
functional/cert/server_cert_b-key.pem
functional/cert/unreadable.pem
localinstall

View file

@ -0,0 +1,39 @@
[submodule "third_party/prometheus-cpp"]
path = third_party/prometheus-cpp
url = https://github.com/jupp0r/prometheus-cpp
branch = master
[submodule "tools/vcpkg"]
path = tools/vcpkg
url = https://github.com/Microsoft/vcpkg
branch = master
[submodule "third_party/ms-gsl"]
path = third_party/ms-gsl
url = https://github.com/microsoft/GSL
branch = main
[submodule "third_party/googletest"]
path = third_party/googletest
url = https://github.com/google/googletest
branch = main
[submodule "third_party/benchmark"]
path = third_party/benchmark
url = https://github.com/google/benchmark
branch = main
[submodule "third_party/opentelemetry-proto"]
path = third_party/opentelemetry-proto
url = https://github.com/open-telemetry/opentelemetry-proto
branch = main
[submodule "third_party/nlohmann-json"]
path = third_party/nlohmann-json
url = https://github.com/nlohmann/json
branch = master
[submodule "third_party/opentracing-cpp"]
path = third_party/opentracing-cpp
url = https://github.com/opentracing/opentracing-cpp.git
branch = master

View file

@ -0,0 +1,31 @@
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
# include-what-you-use mapping file
[
# Work around for C++ STL
{ "include": ["<bits/chrono.h>", "private", "<chrono>", "public"] },
{ "include": ["<bits/std_abs.h>", "private", "<cstdlib>", "public"] },
{ "include": ["<ext/alloc_traits.h>", "private", "<memory>", "public"] },
{ "include": ["<bits/types/struct_tm.h>", "private", "<time.h>", "public"] },
{ "include": ["<bits/types/struct_FILE.h>", "private", "<stdio.h>", "public"] },
# Local opentelemetry-cpp style
# We prefer to include <gtest/gtest.h> for simplicity
{ "include": ["<gtest/gtest-message.h>", "private", "<gtest/gtest.h>", "public"] },
{ "include": ["<gtest/gtest-test-part.h>", "private", "<gtest/gtest.h>", "public"] },
{ "include": ["<gtest/gtest-param-test.h>", "private", "<gtest/gtest.h>", "public"] },
{ "include": ["<gtest/gtest_pred_impl.h>", "private", "<gtest/gtest.h>", "public"] },
{ "include": ["<gtest/gtest-typed-test.h>", "private", "<gtest/gtest.h>", "public"] },
{ "include": ["<gtest/gtest-assertion-result.h>", "private", "<gtest/gtest.h>", "public"] },
# We prefer to include <gmock/gmock.h> for simplicity
{ "include": ["<gmock/gmock-function-mocker.h>", "private", "<gmock/gmock.h>", "public"] },
{ "include": ["<gmock/gmock-spec-builders.h>", "private", "<gmock/gmock.h>", "public"] },
# We prefer to include <curl/curl.h> for simplicity
{ "include": ["<curl/system.h>", "private", "<curl/curl.h>", "public"] },
]

View file

@ -0,0 +1,8 @@
{
"default": true,
"MD013":
{
"code_blocks": false,
"tables": false
}
}

View file

@ -0,0 +1,3 @@
third_party/**
tools/**
examples/otlp/README.md

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,927 @@
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.14)
# See https://cmake.org/cmake/help/latest/policy/CMP0074.html required by
# certain version of zlib which CURL depends on.
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.12")
cmake_policy(SET CMP0074 NEW)
endif()
# Allow to use normal variable for option()
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13")
cmake_policy(SET CMP0077 NEW)
endif()
# Prefer CMAKE_MSVC_RUNTIME_LIBRARY if possible
if(POLICY CMP0091)
cmake_policy(SET CMP0091 NEW)
endif()
if(POLICY CMP0092)
# https://cmake.org/cmake/help/latest/policy/CMP0092.html#policy:CMP0092 Make
# sure the /W3 is not removed from CMAKE_CXX_FLAGS since CMake 3.15
cmake_policy(SET CMP0092 OLD)
endif()
# MSVC RTTI flag /GR should not be not added to CMAKE_CXX_FLAGS by default. @see
# https://cmake.org/cmake/help/latest/policy/CMP0117.html
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.20.0")
cmake_policy(SET CMP0117 NEW)
endif()
project(opentelemetry-cpp)
# Mark variables as used so cmake doesn't complain about them
mark_as_advanced(CMAKE_TOOLCHAIN_FILE)
# Note: CMAKE_FIND_PACKAGE_PREFER_CONFIG requires cmake 3.15. Prefer cmake
# CONFIG search mode to find dependencies. This is important to properly find
# protobuf versions 3.22.0 and above due to the abseil-cpp dependency.
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE)
# Don't use customized cmake modules if vcpkg is used to resolve dependence.
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules/")
endif()
if(EXISTS "${CMAKE_SOURCE_DIR}/third_party_release")
file(STRINGS "${CMAKE_SOURCE_DIR}/third_party_release" third_party_tags)
foreach(third_party ${third_party_tags})
string(REGEX REPLACE "^[ ]+" "" third_party ${third_party})
string(REGEX MATCH "^[^=]+" third_party_name ${third_party})
string(REPLACE "${third_party_name}=" "" third_party_tag ${third_party})
set(${third_party_name} "${third_party_tag}")
endforeach()
endif()
if(DEFINED ENV{ARCH})
# Architecture may be specified via ARCH environment variable
set(ARCH $ENV{ARCH})
else()
# Autodetection logic that populates ARCH variable
if(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64.*|x86_64.*|AMD64.*")
# Windows may report AMD64 even if target is 32-bit
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(ARCH x64)
elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
set(ARCH x86)
endif()
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "i686.*|i386.*|x86.*")
# Windows may report x86 even if target is 64-bit
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(ARCH x64)
elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
set(ARCH x86)
endif()
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "powerpc")
# AIX will report the processor as 'powerpc' even if building in 64-bit mode
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(ARCH ppc64)
else()
set(ARCH ppc32)
endif()
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES
"^(aarch64.*|AARCH64.*|arm64.*|ARM64.*)")
set(ARCH arm64)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm.*|ARM.*)")
set(ARCH arm)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64le")
set(ARCH ppc64le)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64")
set(ARCH ppc64)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(mips.*|MIPS.*)")
set(ARCH mips)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(riscv.*|RISCV.*)")
set(ARCH riscv)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(s390x.*|S390X.*)")
set(ARCH s390x)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(sparc.*|SPARC.*)")
set(ARCH sparc)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(loongarch.*|LOONGARCH.*)")
set(ARCH loongarch)
else()
message(
FATAL_ERROR
"opentelemetry-cpp: unrecognized target processor ${CMAKE_SYSTEM_PROCESSOR} configuration!"
)
endif()
endif()
message(STATUS "Building for architecture ARCH=${ARCH}")
# Autodetect vcpkg toolchain
if(DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
set(CMAKE_TOOLCHAIN_FILE
"$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
CACHE STRING "")
endif()
if(VCPKG_CHAINLOAD_TOOLCHAIN_FILE)
include("${VCPKG_CHAINLOAD_TOOLCHAIN_FILE}")
endif()
option(WITH_ABI_VERSION_1 "ABI version 1" ON)
option(WITH_ABI_VERSION_2 "EXPERIMENTAL: ABI version 2 preview" OFF)
file(READ "${CMAKE_CURRENT_LIST_DIR}/api/include/opentelemetry/version.h"
OPENTELEMETRY_CPP_HEADER_VERSION_H)
#
# We do not want to have WITH_ABI_VERSION = "1" or "2", and instead prefer two
# distinct flags, WITH_ABI_VERSION_1 and WITH_ABI_VERSION_2.
#
# This allows:
#
# * to have a specific option description for each ABI
# * to mark experimental/stable/deprecated on flags, for clarity
# * to search for exact abi usage move easily, discouraging:
#
# * cmake -DWITH_ABI_VERSION=${ARG}
#
# While not supported, having distinct WITH_ABI_VERSION_1 and WITH_ABI_VERSION_2
# flags also opens the possibility to support multiple ABI concurrently, should
# that become necessary.
#
if(WITH_ABI_VERSION_1 AND WITH_ABI_VERSION_2)
#
# Only one ABI is supported in a build.
#
message(
FATAL_ERROR "Set either WITH_ABI_VERSION_1 or WITH_ABI_VERSION_2, not both")
endif()
if(WITH_ABI_VERSION_2)
set(OPENTELEMETRY_ABI_VERSION_NO "2")
elseif(WITH_ABI_VERSION_1)
set(OPENTELEMETRY_ABI_VERSION_NO "1")
else()
if(OPENTELEMETRY_CPP_HEADER_VERSION_H MATCHES
"OPENTELEMETRY_ABI_VERSION_NO[ \t\r\n]+\"?([0-9]+)\"?")
math(EXPR OPENTELEMETRY_ABI_VERSION_NO ${CMAKE_MATCH_1})
else()
message(
FATAL_ERROR
"OPENTELEMETRY_ABI_VERSION_NO not found on ${CMAKE_CURRENT_LIST_DIR}/api/include/opentelemetry/version.h"
)
endif()
endif()
message(STATUS "OPENTELEMETRY_ABI_VERSION_NO=${OPENTELEMETRY_ABI_VERSION_NO}")
if(OPENTELEMETRY_CPP_HEADER_VERSION_H MATCHES
"OPENTELEMETRY_VERSION[ \t\r\n]+\"?([^\"]+)\"?")
set(OPENTELEMETRY_VERSION ${CMAKE_MATCH_1})
else()
message(
FATAL_ERROR
"OPENTELEMETRY_VERSION not found on ${CMAKE_CURRENT_LIST_DIR}/api/include/opentelemetry/version.h"
)
endif()
message(STATUS "OPENTELEMETRY_VERSION=${OPENTELEMETRY_VERSION}")
option(WITH_NO_DEPRECATED_CODE "Do not include deprecated code" OFF)
set(WITH_STL
"OFF"
CACHE STRING "Which version of the Standard Library for C++ to use")
option(WITH_GSL
"Whether to use Guidelines Support Library for C++ latest features" OFF)
set(OPENTELEMETRY_INSTALL_default ON)
if(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
set(OPENTELEMETRY_INSTALL_default OFF)
endif()
option(OPENTELEMETRY_INSTALL "Whether to install opentelemetry targets"
${OPENTELEMETRY_INSTALL_default})
include("${PROJECT_SOURCE_DIR}/cmake/tools.cmake")
if(NOT WITH_STL STREQUAL "OFF")
# These definitions are needed for test projects that do not link against
# opentelemetry-api library directly. We ensure that variant implementation
# (absl::variant or std::variant) in variant unit test code is consistent with
# the global project build definitions. Optimize for speed to reduce the hops
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
if(CMAKE_BUILD_TYPE MATCHES Debug)
# Turn off optimizations for DEBUG
set(MSVC_CXX_OPT_FLAG "/Od")
else()
string(REGEX MATCH "\/O" result ${CMAKE_CXX_FLAGS})
if(NOT ${result} MATCHES "\/O")
set(MSVC_CXX_OPT_FLAG "/O2")
endif()
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MSVC_CXX_OPT_FLAG}")
endif()
endif()
option(WITH_OTLP_RETRY_PREVIEW
"Whether to enable experimental retry functionality" OFF)
option(WITH_OTLP_GRPC_SSL_MTLS_PREVIEW
"Whether to enable mTLS support fro gRPC" OFF)
option(WITH_OTLP_GRPC "Whether to include the OTLP gRPC exporter in the SDK"
OFF)
option(WITH_OTLP_HTTP "Whether to include the OTLP http exporter in the SDK"
OFF)
option(WITH_OTLP_FILE "Whether to include the OTLP file exporter in the SDK"
OFF)
option(
WITH_OTLP_HTTP_COMPRESSION
"Whether to include gzip compression for the OTLP http exporter in the SDK"
OFF)
option(WITH_CURL_LOGGING "Whether to enable select CURL verbosity in OTel logs"
OFF)
option(WITH_ZIPKIN "Whether to include the Zipkin exporter in the SDK" OFF)
option(WITH_PROMETHEUS "Whether to include the Prometheus Client in the SDK"
OFF)
option(WITH_ELASTICSEARCH
"Whether to include the Elasticsearch Client in the SDK" OFF)
option(WITH_NO_GETENV "Whether the platform supports environment variables" OFF)
option(BUILD_TESTING "Whether to enable tests" ON)
option(WITH_BENCHMARK "Whether to build benchmark program" ON)
option(BUILD_W3CTRACECONTEXT_TEST "Whether to build w3c trace context" OFF)
option(OTELCPP_MAINTAINER_MODE "Build in maintainer mode (-Wall -Werror)" OFF)
option(WITH_OPENTRACING "Whether to include the Opentracing shim" OFF)
option(OTELCPP_VERSIONED_LIBS "Whether to generate the versioned shared libs"
OFF)
#
# This option is experimental, subject to change in the spec:
#
# * https://github.com/open-telemetry/opentelemetry-specification/issues/2232
#
option(WITH_REMOVE_METER_PREVIEW
"EXPERIMENTAL, ABI BREAKING: Allow to remove a meter" OFF)
if(OTELCPP_VERSIONED_LIBS AND NOT BUILD_SHARED_LIBS)
message(FATAL_ERROR "OTELCPP_VERSIONED_LIBS=ON requires BUILD_SHARED_LIBS=ON")
endif()
if(WIN32)
option(WITH_ETW "Whether to include the ETW Exporter in the SDK" ON)
else()
if(DEFINED (WITH_ETW))
message(FATAL_ERROR "WITH_ETW is only supported on Windows")
endif()
endif(WIN32)
# Do not convert deprecated message to error
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
add_compile_options(-Wno-error=deprecated-declarations)
endif()
option(
WITH_API_ONLY
"Only build the API (use as a header-only library). Overrides WITH_EXAMPLES and all options to enable exporters"
OFF)
option(WITH_EXAMPLES "Whether to build examples" ON)
# This requires CURL, OFF by default.
option(
WITH_EXAMPLES_HTTP
"Whether to build http client/server examples. Requires WITH_EXAMPLES and CURL"
OFF)
option(WITH_FUNC_TESTS "Whether to build functional tests" ON)
option(WITH_ASYNC_EXPORT_PREVIEW "Whether to enable async export" OFF)
# Exemplar specs status is experimental, so behind feature flag by default
option(WITH_METRICS_EXEMPLAR_PREVIEW
"Whether to enable exemplar within metrics" OFF)
# Experimental, so behind feature flag by default
option(WITH_THREAD_INSTRUMENTATION_PREVIEW
"Whether to enable thread instrumentation" OFF)
option(OPENTELEMETRY_SKIP_DYNAMIC_LOADING_TESTS
"Whether to build test libraries that are always linked as shared libs"
OFF)
#
# Verify options dependencies
#
if(WITH_EXAMPLES_HTTP AND NOT WITH_EXAMPLES)
message(FATAL_ERROR "WITH_EXAMPLES_HTTP=ON requires WITH_EXAMPLES=ON")
endif()
find_package(Threads)
function(install_windows_deps)
# Bootstrap vcpkg from CMake and auto-install deps in case if we are missing
# deps on Windows. Respect the target architecture variable.
set(VCPKG_TARGET_ARCHITECTURE
${ARCH}
PARENT_SCOPE)
message(STATUS "Installing build tools and dependencies...")
set(ENV{ARCH} ${ARCH})
execute_process(
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/tools/setup-buildtools.cmd)
set(CMAKE_TOOLCHAIN_FILE
${CMAKE_CURRENT_SOURCE_DIR}/tools/vcpkg/scripts/buildsystems/vcpkg.cmake
CACHE FILEPATH "")
message(
STATUS
"Make sure that vcpkg.cmake is set as the CMAKE_TOOLCHAIN_FILE at the START of the cmake build process!
Can be command-line arg (cmake -DCMAKE_TOOLCHAIN_FILE=...) or set in your editor of choice."
)
endfunction()
function(set_target_version target_name)
if(OTELCPP_VERSIONED_LIBS)
set_target_properties(
${target_name} PROPERTIES VERSION ${OPENTELEMETRY_VERSION}
SOVERSION ${OPENTELEMETRY_ABI_VERSION_NO})
endif()
endfunction()
if(MSVC)
# Options for Visual C++ compiler: /Zc:__cplusplus - report an updated value
# for recent C++ language standards. Without this option MSVC returns the
# value of __cplusplus="199711L"
if(MSVC_VERSION GREATER 1900)
# __cplusplus flag is not supported by Visual Studio 2015
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:__cplusplus")
endif()
endif()
# include GNUInstallDirs before include cmake/opentelemetry-proto.cmake because
# opentelemetry-proto installs targets to the location variables defined in
# GNUInstallDirs.
include(GNUInstallDirs)
if(WITH_PROMETHEUS)
find_package(prometheus-cpp CONFIG QUIET)
if(NOT prometheus-cpp_FOUND)
message(STATUS "Trying to use local prometheus-cpp from submodule")
if(EXISTS ${PROJECT_SOURCE_DIR}/third_party/prometheus-cpp/.git)
set(SAVED_ENABLE_TESTING ${ENABLE_TESTING})
set(SAVED_CMAKE_CXX_CLANG_TIDY ${CMAKE_CXX_CLANG_TIDY})
set(SAVED_CMAKE_CXX_INCLUDE_WHAT_YOU_USE
${CMAKE_CXX_INCLUDE_WHAT_YOU_USE})
set(ENABLE_TESTING OFF)
set(CMAKE_CXX_CLANG_TIDY "")
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "")
add_subdirectory(third_party/prometheus-cpp)
set(ENABLE_TESTING ${SAVED_ENABLE_TESTING})
set(CMAKE_CXX_CLANG_TIDY ${SAVED_CMAKE_CXX_CLANG_TIDY})
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE
${SAVED_CMAKE_CXX_INCLUDE_WHAT_YOU_USE})
# Get the version of the prometheus-cpp submodule
find_package(Git QUIET)
if(Git_FOUND)
execute_process(
COMMAND ${GIT_EXECUTABLE} describe --tags --always
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/third_party/prometheus-cpp
OUTPUT_VARIABLE prometheus-cpp_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REGEX REPLACE "^v" "" prometheus-cpp_VERSION
"${prometheus-cpp_VERSION}")
endif()
message(
STATUS
"Using local prometheus-cpp from submodule. Version = ${prometheus-cpp_VERSION}"
)
else()
message(
FATAL_ERROR
"\nprometheus-cpp package was not found. Please either provide it manually or clone with submodules. "
"To initialize, fetch and checkout any nested submodules, you can use the following command:\n"
"git submodule update --init --recursive")
endif()
else()
message(STATUS "Using external prometheus-cpp")
endif()
endif()
if(WITH_OTLP_GRPC
OR WITH_OTLP_HTTP
OR WITH_OTLP_FILE)
# Including the CMakeFindDependencyMacro resolves an error from
# gRPCConfig.cmake on some grpc versions. See
# https://github.com/grpc/grpc/pull/33361 for more details.
include(CMakeFindDependencyMacro)
# Protobuf 3.22+ depends on abseil-cpp and must be found using the cmake
# find_package CONFIG search mode. The following attempts to find Protobuf
# using the CONFIG mode first, and if not found, falls back to the MODULE
# mode. See https://gitlab.kitware.com/cmake/cmake/-/issues/24321 for more
# details.
find_package(Protobuf CONFIG)
if(NOT Protobuf_FOUND)
find_package(Protobuf MODULE)
if(Protobuf_FOUND AND Protobuf_VERSION VERSION_GREATER_EQUAL "3.22.0")
message(
WARNING
"Found Protobuf version ${Protobuf_VERSION} using MODULE mode. "
"Linking errors may occur. Protobuf 3.22+ depends on abseil-cpp "
"and should be found using the CONFIG mode.")
endif()
endif()
if(WITH_OTLP_GRPC)
find_package(gRPC CONFIG)
endif()
if((NOT Protobuf_FOUND) OR (WITH_OTLP_GRPC AND NOT gRPC_FOUND))
if(WIN32 AND (NOT DEFINED CMAKE_TOOLCHAIN_FILE))
install_windows_deps()
endif()
if(WIN32 AND (NOT DEFINED CMAKE_TOOLCHAIN_FILE))
message(FATAL_ERROR "Windows dependency installation failed!")
endif()
if(WIN32)
include(${CMAKE_TOOLCHAIN_FILE})
endif()
if(NOT Protobuf_FOUND)
find_package(Protobuf CONFIG REQUIRED)
endif()
if(NOT gRPC_FOUND AND WITH_OTLP_GRPC)
find_package(gRPC CONFIG)
endif()
if(WIN32)
# Always use x64 protoc.exe
if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
set(Protobuf_PROTOC_EXECUTABLE
${CMAKE_CURRENT_SOURCE_DIR}/tools/vcpkg/packages/protobuf_x64-windows/tools/protobuf/protoc.exe
)
endif()
endif()
endif()
# Latest Protobuf imported targets and without legacy module support
if(TARGET protobuf::protoc)
if(CMAKE_CROSSCOMPILING AND Protobuf_PROTOC_EXECUTABLE)
set(PROTOBUF_PROTOC_EXECUTABLE ${Protobuf_PROTOC_EXECUTABLE})
else()
project_build_tools_get_imported_location(PROTOBUF_PROTOC_EXECUTABLE
protobuf::protoc)
# If protobuf::protoc is not a imported target, then we use the target
# directly for fallback
if(NOT PROTOBUF_PROTOC_EXECUTABLE)
set(PROTOBUF_PROTOC_EXECUTABLE protobuf::protoc)
endif()
endif()
elseif(Protobuf_PROTOC_EXECUTABLE)
# Some versions of FindProtobuf.cmake uses mixed case instead of uppercase
set(PROTOBUF_PROTOC_EXECUTABLE ${Protobuf_PROTOC_EXECUTABLE})
endif()
include(CMakeDependentOption)
message(STATUS "PROTOBUF_PROTOC_EXECUTABLE=${PROTOBUF_PROTOC_EXECUTABLE}")
set(SAVED_CMAKE_CXX_CLANG_TIDY ${CMAKE_CXX_CLANG_TIDY})
set(CMAKE_CXX_CLANG_TIDY "")
include(cmake/opentelemetry-proto.cmake)
set(CMAKE_CXX_CLANG_TIDY ${SAVED_CMAKE_CXX_CLANG_TIDY})
endif()
#
# Do we need HTTP CLIENT CURL ?
#
if(WITH_OTLP_HTTP
OR WITH_ELASTICSEARCH
OR WITH_ZIPKIN
OR BUILD_W3CTRACECONTEXT_TEST
OR WITH_EXAMPLES_HTTP)
set(WITH_HTTP_CLIENT_CURL ON)
else()
set(WITH_HTTP_CLIENT_CURL OFF)
endif()
#
# Do we need CURL ?
#
if((NOT WITH_API_ONLY) AND WITH_HTTP_CLIENT_CURL)
# No specific version required.
find_package(CURL REQUIRED)
# Set the CURL_VERSION from the legacy CURL_VERSION_STRING Required for CMake
# versions below 4.0
if(NOT DEFINED CURL_VERSION AND DEFINED CURL_VERSION_STRING)
set(CURL_VERSION ${CURL_VERSION_STRING})
endif()
endif()
#
# Do we need ZLIB ?
#
if((NOT WITH_API_ONLY)
AND WITH_HTTP_CLIENT_CURL
AND WITH_OTLP_HTTP_COMPRESSION)
# No specific version required.
find_package(ZLIB REQUIRED)
# Set the ZLIB_VERSION from the legacy ZLIB_VERSION_STRING Required for CMake
# versions below 3.26
if(NOT DEFINED ZLIB_VERSION AND DEFINED ZLIB_VERSION_STRING)
set(ZLIB_VERSION ${ZLIB_VERSION_STRING})
endif()
endif()
#
# Do we need NLOHMANN_JSON ?
#
if(WITH_ELASTICSEARCH
OR WITH_ZIPKIN
OR WITH_OTLP_HTTP
OR WITH_OTLP_FILE
OR BUILD_W3CTRACECONTEXT_TEST
OR WITH_ETW)
set(USE_NLOHMANN_JSON ON)
else()
set(USE_NLOHMANN_JSON OFF)
endif()
if((NOT WITH_API_ONLY) AND USE_NLOHMANN_JSON)
include(cmake/nlohmann-json.cmake)
endif()
if(OTELCPP_MAINTAINER_MODE)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
message(STATUS "Building with gcc in maintainer mode.")
add_compile_options(-Wall)
add_compile_options(-Werror)
add_compile_options(-Wextra)
# Tested with GCC 9.4 on github.
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 9.4)
message(STATUS "Building with additional warnings for gcc.")
# Relaxed warnings
# Enforced warnings
# C++ options only
add_compile_options($<$<STREQUAL:$<COMPILE_LANGUAGE>,CXX>:-Wextra-semi>)
add_compile_options(
$<$<STREQUAL:$<COMPILE_LANGUAGE>,CXX>:-Woverloaded-virtual>)
add_compile_options(
$<$<STREQUAL:$<COMPILE_LANGUAGE>,CXX>:-Wsuggest-override>)
add_compile_options(
$<$<STREQUAL:$<COMPILE_LANGUAGE>,CXX>:-Wold-style-cast>)
# C and C++
add_compile_options(-Wcast-qual)
add_compile_options(-Wformat-security)
add_compile_options(-Wlogical-op)
add_compile_options(-Wmissing-include-dirs)
add_compile_options(-Wstringop-truncation)
add_compile_options(-Wundef)
add_compile_options(-Wvla)
endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
message(STATUS "Building with clang in maintainer mode.")
add_compile_options(-Wall)
add_compile_options(-Werror)
add_compile_options(-Wextra)
# Tested with Clang 11.0 on github.
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0)
message(STATUS "Building with additional warnings for clang.")
# Relaxed warnings
add_compile_options(-Wno-error=unused-private-field)
# Enforced warnings
add_compile_options(-Wcast-qual)
add_compile_options(-Wconditional-uninitialized)
add_compile_options(-Wextra-semi)
add_compile_options(-Wformat-security)
add_compile_options(-Wheader-hygiene)
add_compile_options(-Winconsistent-missing-destructor-override)
add_compile_options(-Winconsistent-missing-override)
add_compile_options(-Wnewline-eof)
add_compile_options(-Wnon-virtual-dtor)
add_compile_options(-Woverloaded-virtual)
add_compile_options(-Wrange-loop-analysis)
add_compile_options(-Wundef)
add_compile_options(-Wundefined-reinterpret-cast)
add_compile_options(-Wvla)
add_compile_options(-Wold-style-cast)
endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
message(STATUS "Building with msvc in maintainer mode.")
add_compile_options(/WX)
add_compile_options(/W4)
# Relaxed warnings
add_compile_options(/wd4100)
add_compile_options(/wd4125)
add_compile_options(/wd4566)
add_compile_options(/wd4127)
add_compile_options(/wd4512)
add_compile_options(/wd4267)
add_compile_options(/wd4996)
# Enforced warnings
add_compile_options(/we4265) # 'class': class has virtual functions, but
# destructor is not virtual
add_compile_options(/we5204) # A class with virtual functions has
# non-virtual trivial destructor.
elseif()
message(FATAL_ERROR "Building with unknown compiler in maintainer mode.")
endif()
endif(OTELCPP_MAINTAINER_MODE)
list(APPEND CMAKE_PREFIX_PATH "${CMAKE_BINARY_DIR}")
include(CTest)
if(BUILD_TESTING)
if(EXISTS ${CMAKE_BINARY_DIR}/lib/libgtest.a)
# Prefer GTest from build tree. GTest is not always working with
# CMAKE_PREFIX_PATH
set(GTEST_INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/third_party/googletest/googletest/include
${CMAKE_CURRENT_SOURCE_DIR}/third_party/googletest/googlemock/include)
if(TARGET gtest)
set(GTEST_BOTH_LIBRARIES gtest gtest_main)
else()
set(GTEST_BOTH_LIBRARIES ${CMAKE_BINARY_DIR}/lib/libgtest.a
${CMAKE_BINARY_DIR}/lib/libgtest_main.a)
endif()
elseif(WIN32)
# Make sure we are always bootsrapped with vcpkg on Windows
find_package(GTest)
if(NOT (GTEST_FOUND OR GTest_FOUND))
if(DEFINED CMAKE_TOOLCHAIN_FILE)
message(
FATAL_ERROR
"Pleaes install GTest with the CMAKE_TOOLCHAIN_FILE at ${CMAKE_TOOLCHAIN_FILE}"
)
else()
install_windows_deps()
include(${CMAKE_TOOLCHAIN_FILE})
find_package(GTest REQUIRED)
endif()
endif()
else()
# Prefer GTest installed by OS distro, brew or vcpkg package manager
find_package(GTest REQUIRED)
endif()
if(NOT GTEST_BOTH_LIBRARIES)
# New GTest package names
if(TARGET GTest::gtest)
set(GTEST_BOTH_LIBRARIES GTest::gtest GTest::gtest_main)
elseif(TARGET GTest::GTest)
set(GTEST_BOTH_LIBRARIES GTest::GTest GTest::Main)
endif()
endif()
if(GTEST_INCLUDE_DIRS)
include_directories(SYSTEM ${GTEST_INCLUDE_DIRS})
endif()
message(STATUS "GTEST_INCLUDE_DIRS = ${GTEST_INCLUDE_DIRS}")
message(STATUS "GTEST_BOTH_LIBRARIES = ${GTEST_BOTH_LIBRARIES}")
# Try to find gmock
if(NOT GMOCK_LIB AND TARGET GTest::gmock)
set(GMOCK_LIB GTest::gmock)
elseif(MSVC)
# Explicitly specify that we consume GTest from shared library. The rest of
# code logic below determines whether we link Release or Debug flavor of the
# library. These flavors have different prefix on Windows, gmock and gmockd
# respectively.
add_definitions(-DGTEST_LINKED_AS_SHARED_LIBRARY=1)
if(GMOCK_LIB)
# unset GMOCK_LIB to force find_library to redo the lookup, as the cached
# entry could cause linking to incorrect flavor of gmock and leading to
# runtime error.
unset(GMOCK_LIB CACHE)
endif()
endif()
if(NOT GMOCK_LIB)
if(MSVC AND CMAKE_BUILD_TYPE STREQUAL "Debug")
find_library(GMOCK_LIB gmockd PATH_SUFFIXES lib)
else()
find_library(GMOCK_LIB gmock PATH_SUFFIXES lib)
endif()
# Reset GMOCK_LIB if it was not found, or some target may link
# GMOCK_LIB-NOTFOUND
if(NOT GMOCK_LIB)
unset(GMOCK_LIB)
unset(GMOCK_LIB CACHE)
endif()
endif()
enable_testing()
if(WITH_BENCHMARK)
# Benchmark respects the CMAKE_PREFIX_PATH
find_package(benchmark CONFIG REQUIRED)
endif()
endif()
# Record build config and versions
message(STATUS "---------------------------------------------")
message(STATUS "build settings")
message(STATUS "---------------------------------------------")
message(STATUS "OpenTelemetry: ${OPENTELEMETRY_VERSION}")
message(STATUS "OpenTelemetry ABI: ${OPENTELEMETRY_ABI_VERSION_NO}")
message(STATUS "ARCH: ${ARCH}")
message(STATUS "CXX: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}")
message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
message(STATUS "CXXFLAGS: ${CMAKE_CXX_FLAGS}")
message(STATUS "CMAKE_CXX_STANDARD: ${CMAKE_CXX_STANDARD}")
message(STATUS "CMAKE_TOOLCHAIN_FILE: ${CMAKE_TOOLCHAIN_FILE}")
message(STATUS "BUILD_SHARED_LIBS: ${BUILD_SHARED_LIBS}")
message(STATUS "---------------------------------------------")
message(STATUS "opentelemetry-cpp build options")
message(STATUS "---------------------------------------------")
message(STATUS "WITH_API_ONLY: ${WITH_API_ONLY}")
message(STATUS "WITH_NO_DEPRECATED_CODE: ${WITH_NO_DEPRECATED_CODE}")
message(STATUS "WITH_ABI_VERSION_1: ${WITH_ABI_VERSION_1}")
message(STATUS "WITH_ABI_VERSION_2: ${WITH_ABI_VERSION_2}")
message(STATUS "OTELCPP_VERSIONED_LIBS: ${OTELCPP_VERSIONED_LIBS}")
message(STATUS "OTELCPP_MAINTAINER_MODE: ${OTELCPP_MAINTAINER_MODE}")
message(STATUS "WITH_STL: ${WITH_STL}")
message(STATUS "WITH_GSL: ${WITH_GSL}")
message(STATUS "WITH_NO_GETENV: ${WITH_NO_GETENV}")
message(STATUS "---------------------------------------------")
message(STATUS "opentelemetry-cpp cmake component options")
message(STATUS "---------------------------------------------")
message(STATUS "WITH_OTLP_GRPC: ${WITH_OTLP_GRPC}")
message(STATUS "WITH_OTLP_HTTP: ${WITH_OTLP_HTTP}")
message(STATUS "WITH_OTLP_FILE: ${WITH_OTLP_FILE}")
message(STATUS "WITH_HTTP_CLIENT_CURL: ${WITH_HTTP_CLIENT_CURL}")
message(STATUS "WITH_ZIPKIN: ${WITH_ZIPKIN}")
message(STATUS "WITH_PROMETHEUS: ${WITH_PROMETHEUS}")
message(STATUS "WITH_ELASTICSEARCH: ${WITH_ELASTICSEARCH}")
message(STATUS "WITH_OPENTRACING: ${WITH_OPENTRACING}")
message(STATUS "WITH_ETW: ${WITH_ETW}")
message(STATUS "OPENTELEMETRY_BUILD_DLL: ${OPENTELEMETRY_BUILD_DLL}")
message(STATUS "---------------------------------------------")
message(STATUS "feature preview options")
message(STATUS "---------------------------------------------")
message(STATUS "WITH_ASYNC_EXPORT_PREVIEW: ${WITH_ASYNC_EXPORT_PREVIEW}")
message(
STATUS
"WITH_THREAD_INSTRUMENTATION_PREVIEW: ${WITH_THREAD_INSTRUMENTATION_PREVIEW}"
)
message(
STATUS "WITH_METRICS_EXEMPLAR_PREVIEW: ${WITH_METRICS_EXEMPLAR_PREVIEW}")
message(STATUS "WITH_REMOVE_METER_PREVIEW: ${WITH_REMOVE_METER_PREVIEW}")
message(
STATUS "WITH_OTLP_GRPC_SSL_MTLS_PREVIEW: ${WITH_OTLP_GRPC_SSL_MTLS_PREVIEW}")
message(STATUS "WITH_OTLP_RETRY_PREVIEW: ${WITH_OTLP_RETRY_PREVIEW}")
message(STATUS "---------------------------------------------")
message(STATUS "third-party options")
message(STATUS "---------------------------------------------")
message(STATUS "WITH_NLOHMANN_JSON: ${USE_NLOHMANN_JSON}")
message(STATUS "WITH_CURL_LOGGING: ${WITH_CURL_LOGGING}")
message(STATUS "WITH_OTLP_HTTP_COMPRESSION: ${WITH_OTLP_HTTP_COMPRESSION}")
message(STATUS "---------------------------------------------")
message(STATUS "examples and test options")
message(STATUS "---------------------------------------------")
message(STATUS "WITH_BENCHMARK: ${WITH_BENCHMARK}")
message(STATUS "WITH_EXAMPLES: ${WITH_EXAMPLES}")
message(STATUS "WITH_EXAMPLES_HTTP: ${WITH_EXAMPLES_HTTP}")
message(STATUS "WITH_FUNC_TESTS: ${WITH_FUNC_TESTS}")
message(STATUS "BUILD_W3CTRACECONTEXT_TEST: ${BUILD_W3CTRACECONTEXT_TEST}")
message(STATUS "BUILD_TESTING: ${BUILD_TESTING}")
message(STATUS "---------------------------------------------")
message(STATUS "versions")
message(STATUS "---------------------------------------------")
message(STATUS "CMake: ${CMAKE_VERSION}")
message(STATUS "GTest: ${GTest_VERSION}")
message(STATUS "benchmark: ${benchmark_VERSION}")
if(WITH_GSL)
message(STATUS "GSL: ${GSL_VERSION}")
endif()
if(absl_FOUND)
message(STATUS "Abseil: ${absl_VERSION}")
endif()
if(Protobuf_FOUND)
message(STATUS "Protobuf: ${Protobuf_VERSION}")
endif()
if(gRPC_FOUND)
message(STATUS "gRPC: ${gRPC_VERSION}")
endif()
if(CURL_FOUND)
message(STATUS "CURL: ${CURL_VERSION}")
endif()
if(ZLIB_FOUND)
message(STATUS "ZLIB: ${ZLIB_VERSION}")
endif()
if(USE_NLOHMANN_JSON)
message(STATUS "nlohmann-json: ${nlohmann_json_VERSION}")
endif()
if(prometheus-cpp_FOUND)
message(STATUS "prometheus-cpp: ${prometheus-cpp_VERSION}")
endif()
message(STATUS "---------------------------------------------")
include("${PROJECT_SOURCE_DIR}/cmake/otel-install-functions.cmake")
include(CMakePackageConfigHelpers)
if(DEFINED OPENTELEMETRY_BUILD_DLL)
if(NOT WIN32)
message(FATAL_ERROR "Build DLL is only supported on Windows!")
endif()
if(NOT MSVC)
message(WARNING "Build DLL is supposed to work with MSVC!")
endif()
if(WITH_STL)
message(
WARNING "Build DLL with C++ STL could cause binary incompatibility!")
endif()
add_definitions(-DOPENTELEMETRY_BUILD_EXPORT_DLL)
endif()
add_subdirectory(api)
if(WITH_OPENTRACING)
find_package(OpenTracing CONFIG QUIET)
if(NOT OpenTracing_FOUND)
set(OPENTRACING_DIR "third_party/opentracing-cpp")
message(STATUS "Trying to use local ${OPENTRACING_DIR} from submodule")
if(EXISTS "${PROJECT_SOURCE_DIR}/${OPENTRACING_DIR}/.git")
set(SAVED_BUILD_TESTING ${BUILD_TESTING})
set(BUILD_TESTING OFF)
set(SAVED_CMAKE_CXX_INCLUDE_WHAT_YOU_USE
${CMAKE_CXX_INCLUDE_WHAT_YOU_USE})
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "")
add_subdirectory(${OPENTRACING_DIR})
set(BUILD_TESTING ${SAVED_BUILD_TESTING})
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE
${SAVED_CMAKE_CXX_INCLUDE_WHAT_YOU_USE})
else()
message(
FATAL_ERROR
"\nopentracing-cpp package was not found. Please either provide it manually or clone with submodules. "
"To initialize, fetch and checkout any nested submodules, you can use the following command:\n"
"git submodule update --init --recursive")
endif()
else()
message(STATUS "Using external opentracing-cpp")
endif()
add_subdirectory(opentracing-shim)
endif()
if(NOT WITH_API_ONLY)
set(BUILD_TESTING ${BUILD_TESTING})
add_subdirectory(sdk)
add_subdirectory(ext)
add_subdirectory(exporters)
if(BUILD_TESTING)
add_subdirectory(test_common)
endif()
if(WITH_EXAMPLES)
add_subdirectory(examples)
endif()
if(WITH_FUNC_TESTS)
add_subdirectory(functional)
endif()
endif()
include(cmake/opentelemetry-build-external-component.cmake)
include(cmake/patch-imported-config.cmake)
if(OPENTELEMETRY_INSTALL)
# Install the cmake config and version files
otel_install_cmake_config()
# Install the components and associated files
otel_install_components()
# Install the thirdparty dependency definition file
otel_install_thirdparty_definitions()
if(BUILD_PACKAGE)
include(cmake/package.cmake)
include(CPack)
endif()
endif()

View file

@ -0,0 +1,126 @@
{
"configurations": [
{
"name": "nostd-x64-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"inheritEnvironments": [
"msvc_x64_x64"
],
"buildRoot": "${projectDir}\\out\\vs2019\\${name}",
"installRoot": "${projectDir}\\out\\vs2019\\${name}\\install",
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": "",
"variables": [
{
"name": "WITH_OTLP_GRPC",
"value": "True",
"type": "BOOL"
},
{
"name": "WITH_EXAMPLES",
"value": "true",
"type": "BOOL"
}
]
},
{
"name": "nostd-x64-Release",
"generator": "Ninja",
"configurationType": "Release",
"inheritEnvironments": [
"msvc_x64_x64"
],
"buildRoot": "${projectDir}\\out\\vs2019\\${name}",
"installRoot": "${projectDir}\\out\\vs2019\\${name}\\install",
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": "",
"cmakeToolchain": "",
"variables": [
{
"name": "WITH_OTLP_GRPC",
"value": "True",
"type": "BOOL"
},
{
"name": "WITH_EXAMPLES",
"value": "true",
"type": "BOOL"
}
]
},
{
"name": "stdlib-x64-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"inheritEnvironments": [
"msvc_x64_x64"
],
"buildRoot": "${projectDir}\\out\\vs2019\\${name}",
"installRoot": "${projectDir}\\out\\vs2019\\${name}\\install",
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": "",
"variables": [
{
"name": "WITH_STL",
"value": "True",
"type": "BOOL"
},
{
"name": "WITH_OTLP_GRPC",
"value": "True",
"type": "BOOL"
},
{
"name": "WITH_EXAMPLES",
"value": "true",
"type": "BOOL"
},
{
"name": "WITH_PROMETHEUS",
"value": "True",
"type": "BOOL"
}
]
},
{
"name": "stdlib-x64-Release",
"generator": "Ninja",
"configurationType": "Release",
"inheritEnvironments": [
"msvc_x64_x64"
],
"buildRoot": "${projectDir}\\out\\vs2019\\${name}",
"installRoot": "${projectDir}\\out\\vs2019\\${name}\\install",
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": "",
"cmakeToolchain": "",
"variables": [
{
"name": "WITH_STL",
"value": "True",
"type": "BOOL"
},
{
"name": "WITH_OTLP_GRPC",
"value": "True",
"type": "BOOL"
},
{
"name": "WITH_EXAMPLES",
"value": "true",
"type": "BOOL"
},
{
"name": "WITH_PROMETHEUS",
"value": "True",
"type": "BOOL"
}
]
}
]
}

View file

@ -0,0 +1,3 @@
# OpenTelemetry Community Code of Conduct
OpenTelemetry follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).

View file

@ -0,0 +1,322 @@
# Contributing to opentelemetry-cpp
The OpenTelemetry C/C++ special interest group (SIG) meets regularly. See the
OpenTelemetry [community](https://github.com/open-telemetry/community#cc-sdk)
repo for information on this and other language SIGs.
See the [public meeting
notes](https://docs.google.com/document/d/1i1E4-_y4uJ083lCutKGDhkpi3n4_e774SBLi9hPLocw/edit)
for a summary description of past meetings. To request edit access, join the
meeting or get in touch on
[Slack](https://cloud-native.slack.com/archives/C01N3AT62SJ).
See the [community membership
document](https://github.com/open-telemetry/community/blob/main/community-membership.md)
on how to become a
[**Member**](https://github.com/open-telemetry/community/blob/main/community-membership.md#member),
[**Approver**](https://github.com/open-telemetry/community/blob/main/community-membership.md#approver)
and
[**Maintainer**](https://github.com/open-telemetry/community/blob/main/community-membership.md#maintainer).
## Development
OpenTelemetry C++ uses the [Google naming
convention](https://google.github.io/styleguide/cppguide.html#Naming).
Code is formatted automatically and enforced by CI.
### Build and Run Code Examples
Note: these instructions apply to examples configured with Bazel, see
example-specific documentation for other build automation tools.
Install the latest bazel version by following the steps listed
[here](https://docs.bazel.build/versions/master/install.html).
Select an example of interest from the [examples
folder](https://github.com/open-telemetry/opentelemetry-cpp/tree/main/examples).
Inside each example directory is a `BUILD` file containing instructions for
Bazel. Find the binary name of your example by inspecting the contents of this
`BUILD` file.
Build the example from the root of the opentelemetry-cpp directory using Bazel.
Replace `<binary name>` with the identifier found in the previous step:
```sh
bazel build //examples/<example directory name>:<binary name>
```
Run the resulting executable to see telemetry from the application as it calls
the instrumented library: </li>
```sh
bazel-bin/examples/<example directory name>/<binary name>
```
For instance, building and running the `simple` example can be done as follows:
```sh
bazel build //examples/simple:example_simple
bazel-bin/examples/simple/example_simple
```
### DevContainer Setup for Project
This guide provides instructions on how to set up and use the development
container (`devcontainer`) environment to streamline testing and development
for this project. With the DevContainer, you can work in a consistent environment
configured with all the necessary dependencies and tools.
#### Prerequisites
Before getting started, ensure you have the following installed:
* **Docker**: DevContainers require Docker for containerization.
* **Visual Studio Code (VSCode)** with the **Remote - Containers** extension.
#### Getting Started
* **Open the Project in DevContainer**:
Open the project in VSCode. When prompted to "Reopen in Container," select
this option. If youre not prompted, you can manually open the container by
selecting **Remote-Containers: Reopen in Container** from the command palette
(`F1` or `Ctrl+Shift+P`).
* **Container Setup**:
The DevContainer environment will automatically build based on the configuration
files provided (e.g., `.devcontainer/devcontainer.json`). This setup will install
required dependencies, tools, and environment variables needed for the project.
* **Container Customization**:
See `.devcontainer/README.md` for devcontainer configuration options.
#### Available Commands
Once inside the DevContainer, you can use the following commands to run tests
and CI workflows.
##### 1. Run Tests with Bazelisk
To run tests with Bazelisk using specific compilation options, use:
```bash
bazelisk-linux-amd64 test --copt=-DENABLE_LOGS_PREVIEW
--test_output=errors --cache_test_results=no --copt=-DENABLE_TEST //exporters/otlp/...
```
###### Command Breakdown
* `--copt=-DENABLE_LOGS_PREVIEW`: Enables preview logs.
* `--test_output=errors`: Shows only the errors in the test output.
* `--cache_test_results=no`: Forces Bazel to re-run tests without caching.
* `--copt=-DENABLE_TEST`: Enables testing capabilities for the target code.
* `//exporters/otlp/...`: Specifies the test target path.
##### 2. Run CI Script
You can also run the CI script provided to perform testing with the
following command as an
example:
```bash
bash ci/do_ci.sh cmake.exporter.otprotocol.test
```
This command initiates the CI pipeline, executing tests specifically for the
**cmake.exporter.otprotocol** module.
#### Troubleshooting
If you encounter issues:
* **Rebuild the DevContainer**: From the command palette, run
**Remote-Containers: Rebuild Container** to reinitialize the environment.
* **Check Bazelisk and CI Script Logs**: Inspect logs for any configuration or
dependency issues.
#### Additional Notes
* You can adjust compiler options (`--copt`) as needed to test additional flags
or enable/disable specific features.
* The test results will be displayed in the terminal within the DevContainer for
easy debugging.
#### Resources
* **Bazelisk Documentation**: [https://github.com/bazelbuild/bazelisk](https://github.com/bazelbuild/bazelisk)
* **VSCode DevContainer Documentation**: [https://code.visualstudio.com/docs/remote/containers](https://code.visualstudio.com/docs/remote/containers)
### Docker Development Image
The `.devcontainer/Dockerfile.dev`
dockerfile can be built directly with the following command.
```sh
docker build -t opentelemetry-cpp-dev -f ./.devcontainer/Dockerfile.dev .
```
You can customize the image using build arguments
to match permissions with the host user.
```sh
docker build -t opentelemetry-cpp-dev \
--build-arg USER_UID="$(id -u)" \
--build-arg USER_GID="$(id -g)" \
-f ./.devcontainer/Dockerfile.dev .
```
Run an interactive bash session binding your host
opentelemetry-cpp directory to the container's workspace:
```sh
docker run -it -v "$PWD:/workspaces/opentelemetry-cpp" opentelemetry-cpp-dev bash
```
## Pull Requests
### How to Send Pull Requests
Everyone is welcome to contribute code to `opentelemetry-cpp` via GitHub pull
requests (PRs).
To create a new PR, fork the project in GitHub and clone the upstream repo:
```sh
git clone --recursive https://github.com/open-telemetry/opentelemetry-cpp.git
```
Add your fork as a remote:
```sh
git remote add fork https://github.com/YOUR_GITHUB_USERNAME/opentelemetry-cpp.git
```
If you haven't, make sure you are loading the submodules required to build
OpenTelemetry
```sh
git submodule init
git submodule update
```
The source code is automatically formatted using clang-format.
The output can vary between versions, so make sure to install `clang-format`
version `10.0`, and have `clang-format-10` in your execution path,
so that the helper script `tools/format.sh` can find it.
Check out a new branch, make modifications and push the branch to your fork:
```sh
git checkout -b feature
# edit files
tools/format.sh
git commit
git push fork feature
```
If you made changes to the Markdown documents (`*.md` files), install the latest
[`markdownlint-cli`](https://github.com/igorshubovych/markdownlint-cli) and run:
```sh
markdownlint .
```
If you modified shell scripts (`*.sh` files), install `shellcheck` and run:
```sh
shellcheck --severity=error <path to shell script>.sh
```
Open a pull request against the main `opentelemetry-cpp` repo.
To run tests locally, please read the [CI instructions](ci/README.md).
### How to Receive Comments
* If the PR is not ready for review, please put `[WIP]` in the title, tag it as
`work-in-progress`, or mark it as
[`draft`](https://github.blog/2019-02-14-introducing-draft-pull-requests/).
* Make sure [CLA](https://identity.linuxfoundation.org/projects/cncf) is signed
and CI is clear.
* For non-trivial changes, please update the [CHANGELOG](./CHANGELOG.md).
### How to Get PRs Merged
A PR is considered to be **ready to merge** when:
* It has received two approvals with at least one approval from
[Approver](https://github.com/open-telemetry/community/blob/main/community-membership.md#approver)
/
[Maintainer](https://github.com/open-telemetry/community/blob/main/community-membership.md#maintainer)
(at different company).
* A pull request opened by an Approver / Maintainer can be merged with only one
approval from Approver / Maintainer (at different company).
* Major feedback items/points are resolved.
* It has been open for review for at least one working day. This gives people
reasonable time to review.
* Trivial changes (typo, cosmetic, doc, etc.) don't have to wait for one day.
* Urgent fixes can take exceptions as long as it has been actively communicated.
Any Maintainer can merge the PR once it is **ready to merge**. Maintainer can
make conscious judgement to merge pull requests which have not strictly met
above mentioned requirements.
If a PR has been stuck (e.g. there are lots of debates and people couldn't agree
on each other), the owner should try to get people aligned by:
* Consolidating the perspectives and putting a summary in the PR. It is
recommended to add a link into the PR description, which points to a comment
with a summary in the PR conversation
* Stepping back to see if it makes sense to narrow down the scope of the PR or
split it up.
If none of the above worked and the PR has been stuck for more than 2 weeks, the
owner should bring it to the OpenTelemetry C++ SIG meeting. See
[README.md](README.md#contributing) for the meeting link.
## Design Choices
As with other OpenTelemetry clients, opentelemetry-cpp follows the
[opentelemetry-specification](https://github.com/open-telemetry/opentelemetry-specification).
It's especially valuable to read through the [library
guidelines](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/library-guidelines.md).
## Useful Resources
Hi! If youre looking at this document, these resources will provide you the
knowledge to get started as a newcomer to the OpenTelemetry project. They will
help you understand the OpenTelemetry Project, its components, and specifically
the C++ repository.
### Reading Resources
* Medium
[article](https://medium.com/opentelemetry/how-to-start-contributing-to-opentelemetry-b23991ad91f4)
(October 2019) on how to start contributing to the OpenTelemetry project.
* Medium
[article](https://medium.com/opentelemetry/opentelemetry-beyond-getting-started-5ac43cd0fe26)
(January 2020) describing the overarching goals and use cases for
OpenTelemetry.
### Relevant Documentation
* [OpenTelemetry
Specification](https://github.com/open-telemetry/opentelemetry-specification)
* The OpenTelemetry Specification describes the requirements and expectations
of for all OpenTelemetry implementations.
* Read through the OpenTelemetry C++ documentation
* The
[API](https://opentelemetry-cpp.readthedocs.io/en/latest/api/api.html)
and
[SDK](https://opentelemetry-cpp.readthedocs.io/en/latest/sdk/sdk.html)
documentation provides a lot of information on what the classes and their
functions are used for.
Please contribute! Youre welcome to add more information if you come across any
helpful resources.

View file

@ -0,0 +1,139 @@
# Deprecated
This document lists all the items currently deprecated in opentelemetry-cpp.
Deprecated items will be removed in the future.
## Guidelines
### Maintainer guidelines
See the [deprecation-process](./docs/deprecation-process.md)
## [TEMPLATE]
### New Deprecation Title (Template)
#### Announcement (Template)
#### Motivation (Template)
#### Scope (Template)
#### Mitigation (Template)
#### Planned removal (Template)
## [Platforms]
N/A
## [Compilers]
N/A
## [Third party dependencies]
N/A
## [Build tools]
N/A
## [Build scripts]
N/A
## [opentelemetry-cpp API]
N/A
## [opentelemetry-cpp SDK]
N/A
## [opentelemetry-cpp Exporter]
N/A
## [Documentation]
N/A
## Semantic conventions
### Header files "semantic_conventions.h"
#### Announcement (semantic_conventions.h)
Deprecation is announced as part of the migration to weaver:
* `Version:` release following opentelemetry-cpp 1.17.0
* `Date:` Nov 9, 2024
* `PR:` [PR 3105](https://github.com/open-telemetry/opentelemetry-cpp/pull/3105)
#### Motivation (semantic_conventions.h)
The header files for semantic conventions are generated automatically.
The tooling to generate these files is changing:
* before, the build-tool repository was used
* now, the weaver repository is used
Changes in tooling allows to generate code that is better organized,
with dedicated header files per group of semantic conventions,
instead of a single header file for everything.
#### Scope (semantic_conventions.h)
The following files:
* `api/include/opentelemetry/trace/semantic_conventions.h`
* `sdk/include/opentelemetry/sdk/resource/semantic_conventions.h`
are now deprecated.
They correspond to semantic conventions v1.27.0,
and will no longer be maintained up to date.
These files will be removed in the future.
#### Mitigation (semantic_conventions.h)
Two things have changed:
* the header file to use
* the symbol name to use.
Before, the semantic convention for `url.full` was:
* declared in file `semantic_conventions.h`
* declared as symbol `SemanticConventions::kUrlFull`
Now, the `url.full` convention, which is part or the `url` group, is:
* declared in file `semconv/url_attributes.h`
* declared as symbol `semconv::url::kUrlFull`
Application code that uses semantic conventions must be adjusted
accordingly.
In addition, semantic conventions that are not marked as stable
are generated in a different header file, placed under directory
`incubating`, to better separate stable and non stable code.
For example, file `semconv/incubating/url_attributes.h`
defines `semconv::url::kUrlDomain`,
which is not marked as stable in semconv v1.27.0
#### Planned removal (semantic_conventions.h)
The following files:
* `api/include/opentelemetry/trace/semantic_conventions.h`
* `sdk/include/opentelemetry/sdk/resource/semantic_conventions.h`
will be removed.
The removal date is planned for July 1, 2025.
This allows more than six months for applications to adjust.

View file

@ -0,0 +1,452 @@
# Building opentelemetry-cpp
[CMake](https://cmake.org/) and [Bazel](https://bazel.build) are the official
build systems for opentelemetry-cpp.
## Dependencies
You can link OpenTelemetry C++ SDK with libraries provided in
[dependencies.md](https://github.com/open-telemetry/opentelemetry-cpp/blob/main/docs/dependencies.md)
(complete list of libraries with versions used in our CI can be found
[here](https://github.com/open-telemetry/opentelemetry-cpp/blob/main/third_party_release)).
## Build instructions using CMake
### Prerequisites for CMake build
- A supported platform (e.g. Windows, macOS or Linux). Refer to [Platforms
Supported](./README.md#supported-development-platforms) for more information.
- A compatible C++ compiler supporting at least C++14. Major compilers are
supported. Refer to [Supported Compilers](./README.md#supported-c-versions)
for more information.
- [Git](https://git-scm.com/) for fetching opentelemetry-cpp source code from
repository. To install Git, consult the [Set up
Git](https://help.github.com/articles/set-up-git/) guide on GitHub.
- [CMake](https://cmake.org/) for building opentelemetry-cpp API, SDK with their
unittests. The minimum CMake version is 3.14.
CMake 3.15+ is recommended on Windows due to known CI test failures with 3.14.
To install CMake,
consult the [Installing CMake](https://cmake.org/install/) guide.
- [GoogleTest](https://github.com/google/googletest) framework to build and run
the unittests. Refer to
[third_party_release](https://github.com/open-telemetry/opentelemetry-cpp/blob/main/third_party_release#L5)
for version of GoogleTest used in CI. To install GoogleTest, consult the
[GoogleTest Build
Instructions](https://github.com/google/googletest/blob/master/googletest/README.md#generic-build-instructions).
- [Google Benchmark](https://github.com/google/benchmark) framework to build and
run benchmark tests. Refer to
[third_party_release](https://github.com/open-telemetry/opentelemetry-cpp/blob/main/third_party_release#L4)
for version of Benchmark used in CI. To install Benchmark, consult the
[GoogleBenchmark Build
Instructions](https://github.com/google/benchmark#installation).
- Apart from above core requirements, the Exporters and Propagators have their
build dependencies.
### Building dependencies for the OTLP exporters
The opentelemetry-cpp OTLP exporters depend on Protobuf and gRPC
(in the case of the otlp grpc exporters).
Protobuf (since version 3.22.0) and gRPC depend on Abseil.
For cmake builds, it is best practice to build and install Abseil
, Protobuf, and gPRC as independent packages -
configuring cmake for Protobuf and gRPC to build against
the installed packages instead of using their submodule option.
If building and installing Protobuf and gRPC manually with cmake the
recommended approach is:
1. Choose the desired tag version of grpc. Find the compatible versions of abseil
and protobuf by inspecting the submodules of grpc at that tag.
2. Build and install the required version of abseil
3. Build and install the required version of protobuf
- Set the cmake option of Protobuf to build against the installed
package of Abseil (`protobuf_ABSL_PROVIDER=package`)
4. Build and install the required version of grpc
- Set the cmake option of grpc to build against the installed packages
of Abseil and Protobuf (cmake options - `gRPC_ABSL_PROVIDER=package` and `gRPC_PROTOBUF_PROVIDER=package`)
### Building as standalone CMake Project
1. Getting the opentelemetry-cpp source with its submodules:
```console
# Change to the directory where you want to create the code repository
$ cd ~
$ mkdir source && cd source && git clone --recurse-submodules https://github.com/open-telemetry/opentelemetry-cpp
Cloning into 'opentelemetry-cpp'...
...
Resolving deltas: 100% (3225/3225), done.
$
```
2. Navigate to the repository cloned above, and create the `CMake` build
configuration.
```console
$ cd opentelemetry-cpp
$ mkdir build && cd build && cmake ..
-- The C compiler identification is GNU 9.3.0
-- The CXX compiler identification is GNU 9.3.0
...
-- Configuring done
-- Generating done
-- Build files have been written to: /home/<user>/source/opentelemetry-cpp/build
$
```
Some of the available cmake build variables we can use during cmake
configuration:
- `-DCMAKE_POSITION_INDEPENDENT_CODE=ON` : Please note that with default
configuration, the code is compiled without `-fpic` option, so it is not
suitable for inclusion in shared libraries. To enable the code for
inclusion in shared libraries, this variable is used.
- `-DBUILD_SHARED_LIBS=ON` : To build shared libraries for the targets.
Please refer to note [below](#building-shared-libs-for-windows) for
Windows DLL support.
- `-DWITH_OTLP_GRPC=ON` : To enable building OTLP GRPC exporter.
- `-DWITH_OTLP_HTTP=ON` : To enable building OTLP HTTP exporter.
- `-DWITH_PROMETHEUS=ON` : To enable building prometheus exporter.
- `-DOPENTELEMETRY_INSTALL=ON`: To install `otel-cpp` library needed
for external code linking.
3. Once the build configuration is created, build the CMake targets - this
includes building SDKs and unittests for API and SDK. Note that since API is
header only library, no separate build is triggered for it.
```console
$ cmake --build . --target all
Scanning dependencies of target timestamp_test
[ 0%] Building CXX object api/test/core/CMakeFiles/timestamp_test.dir/timestamp_test.cc.o
[ 1%] Linking CXX executable timestamp_test
...
Scanning dependencies of target w3c_tracecontext_test
[ 99%] Building CXX object ext/test/w3c_tracecontext_test/CMakeFiles/w3c_tracecontext_test.dir/main.cc.o
[100%] Linking CXX executable w3c_tracecontext_test
[100%] Built target w3c_tracecontext_test
$
```
4. Once CMake tests are built, run them with `ctest` command
```console
$ ctest
Test project /tmp/opentelemetry-cpp/build
Start 1: trace.SystemTimestampTest.Construction
...
Start 380: ext.http.urlparser.UrlParserTests.BasicTests
...
100% tests passed, 0 tests failed out of 380
$
```
5. Optionally install the header files for API, and generated targets and header
files for SDK at custom/default install location.
```console
$ cmake --install . --prefix /<install-root>/
-- Installing: /<install-root>/lib/cmake/opentelemetry-cpp/opentelemetry-cpp-config.cmake
-- Installing: /<install-root>/lib/cmake/opentelemetry-cpp/opentelemetry-cpp-config-version.cmake
...
$
```
### Incorporating into an external CMake Project
There are two approaches to incoporate `opentelemetry-cpp` into
an external CMake project:
1. Build and install `opentelemetry-cpp` then use `find_package`
to import its targets
```cmake
# Find all installed components and link all imported targets
find_package(opentelemetry-cpp CONFIG REQUIRED)
...
target_include_directories(foo PRIVATE ${OPENTELEMETRY_CPP_INCLUDE_DIRS})
target_link_libraries(foo PRIVATE ${OPENTELEMETRY_CPP_LIBRARIES})
```
```cmake
# Find a specific component and link its imported target(s)
find_package(opentelemetry-cpp CONFIG REQUIRED COMPONENTS api)
...
target_link_libraries(foo PRIVATE opentelemetry-cpp::api)
```
2. Use CMake's [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html)
module to fetch and build `opentelemetry-cpp` then make its targets available
```cmake
# Fetch from an existing clone and build
include(FetchContent)
FetchContent_Declare(opentelemetry-cpp SOURCE_DIR "<path/to/opentelemetry-cpp>")
FetchContent_MakeAvailable(opentelemetry-cpp)
...
target_link_libraries(foo PRIVATE opentelemetry-cpp::api)
```
```cmake
# Clone and build opentelemetry-cpp from a git tag
include(FetchContent)
FetchContent_Declare(
opentelemetry-cpp
GIT_REPOSITORY https://github.com/open-telemetry/opentelemetry-cpp.git
GIT_TAG v1.20.0)
FetchContent_MakeAvailable(opentelemetry-cpp)
...
target_link_libraries(foo PRIVATE opentelemetry-cpp::api)
```
In both cases the project's built or imported CMake targets will be
available in the `opentelemetry-cpp` namespace (ie: `opentelemetry-cpp::api`)
#### Using opentelemetry-cpp package components
> **Note:** `opentelemetry-cpp` CMake package components were introduced in `v1.21.0`
The `opentelemetry-cpp` package supports using the `COMPONENTS` argument to
`find_package`. The following example illustrates using this feature to include
and link the `api` header only target to an instrumented `foo_lib` while only including
and linking the `sdk` and `otlp_grpc_exporter` targets to the `foo_app`.
```cmake
# foo_lib/CMakeLists.txt
find_package(opentelemetry-cpp CONFIG REQUIRED COMPONENTS api)
add_library(foo_lib foo.cpp)
target_link_libraries(foo_lib PRIVATE opentelemetry-cpp::api)
```
```cmake
# foo_app/CMakeLists.txt
find_package(opentelemetry-cpp CONFIG REQUIRED COMPONENTS api sdk exporters_otlp_grpc)
add_executable(foo_app main.cpp)
target_link_libraries(foo_app PRIVATE foo_lib opentelemetry-cpp::api opentelemetry-cpp::trace opentelemetry-cpp::otlp_grpc_exporter )
```
The following table provides the mapping between components and targets. Components
and targets available in the installation depends on the opentelemetry-cpp package
build configuration.
> **Note:** components `exporters_elasticsearch` and `exporters_etw`
may be moved out of the core package and to `opentelemetry-cpp-contrib`
in a future release
| Component | Targets |
|----------------------------|--------------------------------------------------------------------------------------------------|
| **api** | opentelemetry-cpp::api |
| **sdk** | opentelemetry-cpp::sdk |
| | opentelemetry-cpp::version |
| | opentelemetry-cpp::common |
| | opentelemetry-cpp::resources |
| | opentelemetry-cpp::trace |
| | opentelemetry-cpp::metrics |
| | opentelemetry-cpp::logs |
| **ext_common** | opentelemetry-cpp::ext |
| **ext_http_curl** | opentelemetry-cpp::http_client_curl |
| **ext_dll** | opentelemetry-cpp::opentelemetry_cpp |
| **exporters_in_memory** | opentelemetry-cpp::in_memory_span_exporter |
| | opentelemetry-cpp::in_memory_metric_exporter |
| **exporters_ostream** | opentelemetry-cpp::ostream_log_record_exporter |
| | opentelemetry-cpp::ostream_metrics_exporter |
| | opentelemetry-cpp::ostream_span_exporter |
| **exporters_otlp_common** | opentelemetry-cpp::proto |
| | opentelemetry-cpp::otlp_recordable |
| **exporters_otlp_file** | opentelemetry-cpp::otlp_file_client |
| | opentelemetry-cpp::otlp_file_exporter |
| | opentelemetry-cpp::otlp_file_log_record_exporter |
| | opentelemetry-cpp::otlp_file_metric_exporter |
| **exporters_otlp_grpc** | opentelemetry-cpp::proto_grpc |
| | opentelemetry-cpp::otlp_grpc_client |
| | opentelemetry-cpp::otlp_grpc_exporter |
| | opentelemetry-cpp::otlp_grpc_log_record_exporter |
| | opentelemetry-cpp::otlp_grpc_metrics_exporter |
| **exporters_otlp_http** | opentelemetry-cpp::otlp_http_client |
| | opentelemetry-cpp::otlp_http_exporter |
| | opentelemetry-cpp::otlp_http_log_record_exporter |
| | opentelemetry-cpp::otlp_http_metric_exporter |
| **exporters_prometheus** | opentelemetry-cpp::prometheus_exporter |
| **exporters_elasticsearch**| opentelemetry-cpp::elasticsearch_log_record_exporter |
| **exporters_etw** | opentelemetry-cpp::etw_exporter |
| **exporters_zipkin** | opentelemetry-cpp::zipkin_trace_exporter |
| **shims_opentracing** | opentelemetry-cpp::opentracing_shim |
## Build instructions using Bazel
NOTE: Experimental, and not supported for all the components. Make sure the
[GoogleTest](https://github.com/google/googletest) installation may fail if
there is a different version of googletest already installed in system-defined
path.
### Prerequisites for Bazel build
- A supported platform (e.g. Windows, macOS or Linux). Refer to [Platforms
Supported](./README.md#supported-development-platforms) for more information.
- A compatible C++ compiler supporting at least C++14. Major compilers are
supported. Refer to [Supported Compilers](./README.md#supported-c-versions) for
more information.
- [Git](https://git-scm.com/) for fetching opentelemetry-cpp source code from
repository. To install Git, consult the [Set up
Git](https://help.github.com/articles/set-up-git/) guide on GitHub.
- [Bazel](https://www.bazel.build/) for building opentelemetry-cpp API, SDK with
their unittests. We use 3.7.2 in our build system.
To install Bazel, consult the [Installing
Bazel](https://docs.bazel.build/versions/3.7.0/install.html) guide.
### Building as standalone Bazel Project
1. Getting the opentelemetry-cpp source:
```console
# Change to the directory where you want to create the code repository
$ cd ~
$ mkdir source && cd source
$ git clone https://github.com/open-telemetry/opentelemetry-cpp
Cloning into 'opentelemetry-cpp'...
...
Resolving deltas: 100% (3225/3225), done.
$
```
2. Navigate to the repository cloned above, download the dependencies and build
the source code:
```console
$ cd opentelemetry-cpp
$ bazel build //...
bazel build -- //... -//exporters/otlp/... -//exporters/prometheus/...
Extracting Bazel installation...
Starting local Bazel server and connecting to it...
INFO: Analyzed 121 targets (98 packages loaded, 3815 targets configured).
INFO: Found 121 targets...
INFO: From Compiling sdk/src/trace/tracer_context.cc:
...
```
3. Once Bazel tests are built, run them with `bazel test //...` command
```console
$ bazel test //...
..
$
```
4. The build artifacts will be located under `bazel-bin`
### Incorporating into an existing Bazel Project
- WORKSPACE file:
```console
http_archive(
name = "io_opentelemetry_cpp",
sha256 = "<sha256>",
strip_prefix = "opentelemetry-cpp-1.0.1",
urls = [
"https://github.com/open-telemetry/opentelemetry-cpp/archive/refs/tags/v1.0.1.tar.gz"
],
)
# Load OpenTelemetry dependencies after load.
load("@io_opentelemetry_cpp//bazel:repository.bzl", "opentelemetry_cpp_deps")
opentelemetry_cpp_deps()
# (required after v1.8.0) Load extra dependencies required for OpenTelemetry
load("@io_opentelemetry_cpp//bazel:extra_deps.bzl", "opentelemetry_extra_deps")
opentelemetry_extra_deps()
# Load gRPC dependencies after load.
load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps")
grpc_deps()
# Load extra gRPC dependencies due to https://github.com/grpc/grpc/issues/20511
load("@com_github_grpc_grpc//bazel:grpc_extra_deps.bzl", "grpc_extra_deps")
grpc_extra_deps()
```
- Component level BUILD file:
```console
cc_library(
name = "<name>"
...
deps = [
"@io_opentelemetry_cpp//api",
"@io_opentelemetry_cpp//exporters/otlp:otlp_exporter",
"@io_opentelemetry_cpp//sdk/src/trace",
...
],
...
)
```
## Building shared libs for Windows
Windows DLL build is supported under **preview**. Please check the
[doc](./docs/build-as-dll.md) for more details.
## Generating binary packages
OpenTelemetry C++ supports generating platform specific binary packages from CMake
configuration. The packages generated through this mayn't be production ready,
and user may have to customize it further before using it as distribution.
- Linux : deb, rpm, tgz
- MacOS : tgz
- Windows : NuGet, zip
This requires platform specific package generators already installed. The package
generation can subsequently be enabled by using BUILD_PACKAGE option during cmake
configuration
```console
$ cd opentelemetry-cpp
$ mkdir build && cd build && cmake -DBUILD_PACKAGE=ON ..
-- Package name: opentelemetry-cpp-1.8.1-ubuntu-20.04-x86_64.deb
-- Configuring done
-- Generating done
...
$
```
Once build is complete as specified in [standalone build section](#building-as-standalone-cmake-project),
the package can be generated as below.
```console
$ cpack -C debug
CPack: Create package using DEB
...
CPack: - package: /home/<user>/opentelemetry-cpp/build/opentelemetry-cpp-1.8.1-ubuntu-20.04-x86_64.deb generated.
$
```
## Using Package Managers
If you are using [Conan](https://www.conan.io/) to manage your dependencies, add
[`opentelemetry-cpp/x.y.z`](https://conan.io/center/opentelemetry-cpp) to your
`conanfile`'s requires, where `x.y.z` is the release version you want to use.
Please file issues [here](https://github.com/conan-io/conan-center-index/issues)
if you experience problems with the packages.
If you are using [vcpkg](https://github.com/Microsoft/vcpkg/) on your project
for external dependencies, then you can install the [opentelemetry-cpp
package](https://github.com/microsoft/vcpkg/tree/master/ports/opentelemetry-cpp)
with `vcpkg install opentelemetry-cpp` and follow the then displayed
descriptions. Please see the vcpkg project for any issues regarding the
packaging.
If you are using [alpine linux](https://www.alpinelinux.org/) you can install
the [opentelemetry-cpp packages](https://pkgs.alpinelinux.org/packages?name=opentelemetry-cpp-*)
with `apk add -X http://dl-cdn.alpinelinux.org/alpine/edge/testing opentelemetry-cpp-dev`.
Please note, these packages are not officially provided and maintained by
OpenTelemetry C++ project, and are just listed here to consolidate all such
efforts for ease of developers.

View file

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -0,0 +1,25 @@
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
module(
name = "opentelemetry-cpp",
version = "1.21.0",
compatibility_level = 0,
repo_name = "io_opentelemetry_cpp",
)
bazel_dep(name = "abseil-cpp", version = "20240116.1", repo_name = "com_google_absl")
bazel_dep(name = "bazel_skylib", version = "1.5.0")
bazel_dep(name = "curl", version = "8.8.0")
bazel_dep(name = "grpc", version = "1.63.1.bcr.1", repo_name = "com_github_grpc_grpc")
bazel_dep(name = "nlohmann_json", version = "3.12.0", repo_name = "github_nlohmann_json")
bazel_dep(name = "opentelemetry-proto", version = "1.6.0", repo_name = "com_github_opentelemetry_proto")
bazel_dep(name = "opentracing-cpp", version = "1.6.0", repo_name = "com_github_opentracing")
bazel_dep(name = "platforms", version = "0.0.8")
bazel_dep(name = "prometheus-cpp", version = "1.3.0", repo_name = "com_github_jupp0r_prometheus_cpp")
bazel_dep(name = "protobuf", version = "26.0", repo_name = "com_google_protobuf")
bazel_dep(name = "rules_proto", version = "5.3.0-21.7")
bazel_dep(name = "zlib", version = "1.3.1.bcr.1")
bazel_dep(name = "google_benchmark", version = "1.8.3", dev_dependency = True, repo_name = "com_github_google_benchmark")
bazel_dep(name = "googletest", version = "1.14.0.bcr.1", dev_dependency = True, repo_name = "com_google_googletest")

View file

@ -0,0 +1,127 @@
# OpenTelemetry C++
[![Slack](https://img.shields.io/badge/slack-@cncf/otel/cpp-brightgreen.svg?logo=slack)](https://cloud-native.slack.com/archives/C01N3AT62SJ)
[![codecov.io](https://codecov.io/gh/open-telemetry/opentelemetry-cpp/branch/main/graphs/badge.svg?)](https://codecov.io/gh/open-telemetry/opentelemetry-cpp/)
[![Build
Status](https://github.com/open-telemetry/opentelemetry-cpp/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/open-telemetry/opentelemetry-cpp/actions)
[![Release](https://img.shields.io/github/v/release/open-telemetry/opentelemetry-cpp?include_prereleases&style=)](https://github.com/open-telemetry/opentelemetry-cpp/releases/)
[![FOSSA License Status](https://app.fossa.com/api/projects/custom%2B162%2Fgithub.com%2Fopen-telemetry%2Fopentelemetry-cpp.svg?type=shield&issueType=license)](https://app.fossa.com/projects/custom%2B162%2Fgithub.com%2Fopen-telemetry%2Fopentelemetry-cpp?ref=badge_shield&issueType=license)
[![FOSSA Security Status](https://app.fossa.com/api/projects/custom%2B162%2Fgithub.com%2Fopen-telemetry%2Fopentelemetry-cpp.svg?type=shield&issueType=security)](https://app.fossa.com/projects/custom%2B162%2Fgithub.com%2Fopen-telemetry%2Fopentelemetry-cpp?ref=badge_shield&issueType=security)
The C++ [OpenTelemetry](https://opentelemetry.io/) client.
## Project Status
**Stable** across all 3 signals i.e. `Logs`, `Metrics`, and `Traces`.
See [Spec Compliance
Matrix](https://github.com/open-telemetry/opentelemetry-specification/blob/main/spec-compliance-matrix.md)
to understand which portions of the specification has been implemented in this
repo.
## Supported C++ Versions
Code shipped from this repository generally supports the following versions of
C++ standards:
* ISO/IEC 14882:2014 (C++14)
* ISO/IEC 14882:2017 (C++17)
* ISO/IEC 14882:2020 (C++20)
Any exceptions to this are noted in the individual `README.md` files.
Please note that supporting the [C Programming
Language](https://en.wikipedia.org/wiki/C_(programming_language)) is not a goal
of the current project.
## Supported Development Platforms
Our CI pipeline builds and tests on following `x86-64` platforms:
| Platform | Build type |
|---------------------------------------------------------------------|---------------|
| ubuntu-22.04 (GCC 10, GCC 12, Clang 14) | CMake, Bazel |
| ubuntu-20.04 (GCC 9.4.0 - default compiler) | CMake, Bazel |
| ubuntu-20.04 (GCC 9.4.0 with -std=c++14/17/20 flags) | CMake, Bazel |
| macOS 12.7 (Xcode 14.2) | Bazel |
| Windows Server 2019 (Visual Studio Enterprise 2019) | CMake, Bazel |
| Windows Server 2022 (Visual Studio Enterprise 2022) | CMake |
In general, the code shipped from this repository should build on all platforms
having C++ compiler with [supported C++ standards](#supported-c-versions).
## Dependencies
Please refer to [Dependencies.md](docs/dependencies.md) for OSS Dependencies and
license requirements.
## Installation
Please refer to [INSTALL.md](./INSTALL.md).
## Getting Started
As an application owner or the library author, you can find the getting started
guide and reference documentation on
[opentelemetry-cpp.readthedocs.io](https://opentelemetry-cpp.readthedocs.io/en/latest/)
The `examples/simple` directory contains a minimal program demonstrating how to
instrument a small library using a simple `processor` and console `exporter`,
along with build files for CMake and Bazel.
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md)
We meet weekly, and the time of the meeting alternates between Monday at 13:00
PT and Wednesday at 9:00 PT. The meeting is subject to change depending on
contributors' availability. Check the [OpenTelemetry community
calendar](https://github.com/open-telemetry/community#calendar)
for specific dates and Zoom meeting links.
Meeting notes are available as a public [Google
doc](https://docs.google.com/document/d/1i1E4-_y4uJ083lCutKGDhkpi3n4_e774SBLi9hPLocw/edit?usp=sharing).
For edit access, get in touch on
[Slack](https://cloud-native.slack.com/archives/C01N3AT62SJ).
[Maintainers](https://github.com/open-telemetry/community/blob/main/community-membership.md#maintainer)
([@open-telemetry/cpp-maintainers](https://github.com/orgs/open-telemetry/teams/cpp-maintainers)):
* [Ehsan Saei](https://github.com/esigo)
* [Lalit Kumar Bhasin](https://github.com/lalitb), Microsoft
* [Marc Alff](https://github.com/marcalff), Oracle
* [Tom Tan](https://github.com/ThomsonTan), Microsoft
[Approvers](https://github.com/open-telemetry/community/blob/main/community-membership.md#approver)
([@open-telemetry/cpp-approvers](https://github.com/orgs/open-telemetry/teams/cpp-approvers)):
* [Doug Barker](https://github.com/dbarker)
* [Josh Suereth](https://github.com/jsuereth), Google
* [Pranav Sharma](https://github.com/psx95), Google
* [WenTao Ou](https://github.com/owent), Tencent
[Emeritus
Maintainer/Approver/Triager](https://github.com/open-telemetry/community/blob/main/community-membership.md#emeritus-maintainerapprovertriager):
* [Alolita Sharma](https://github.com/alolita)
* [Emil Mikulic](https://github.com/g-easy)
* [Jodee Varney](https://github.com/jodeev)
* [Johannes Tax](https://github.com/pyohannes)
* [Max Golovanov](https://github.com/maxgolov)
* [Reiley Yang](https://github.com/reyang)
* [Ryan Burn](https://github.com/rnburn)
### Thanks to all the people who have contributed
[![contributors](https://contributors-img.web.app/image?repo=open-telemetry/opentelemetry-cpp)](https://github.com/open-telemetry/opentelemetry-cpp/graphs/contributors)
## Release Schedule
See the [release
notes](https://github.com/open-telemetry/opentelemetry-cpp/releases) for
existing releases.
See the [project
milestones](https://github.com/open-telemetry/opentelemetry-cpp/milestones) for
details on upcoming releases. The dates and features described in issues and
milestones are estimates, and subject to change.

View file

@ -0,0 +1,96 @@
# Release Process
## Pre Release
1: Upgrade to latest [dependencies](docs/maintaining-dependencies.md)
if required.
2: Make sure all relevant changes for this release are included under
`Unreleased` section in `CHANGELOG.md` and are in language that non-contributors
to the project can understand.
3: Run the pre-release script. It creates a branch `pre_release_<new-tag>` and
updates `CHANGELOG.md` with the `<new-tag>`:
```sh
./buildscripts/pre_release.sh -t <new-tag>
```
4: Verify that CHANGELOG.md is updated properly:
```sh
git diff main
```
5: Push the changes to upstream and create a Pull Request on GitHub. Be sure to
include the curated changes from the [Changelog](./CHANGELOG.md) in the
description.
## Tag
Once the above Pull Request has been approved and merged it is time to tag the
merged commit.
***IMPORTANT***: It is critical you use the same tag that you used in the
Pre-Release step! Failure to do so will leave things in a broken state.
1: Note down the commit hash of the master branch after above PR request is
merged: `<commit-hash>`
```sh
git show -s --format=%H
```
2: Create a github tag on this commit hash:
```sh
git tag -a "<new-tag>" -s -m "Version <new-tag>" "<commit-hash>"
```
3: Push tag to upstream remote
```sh
git push upstream
```
## Versioning
Once tag is created, it's time to use that tag for Runtime Versioning
1: Create a new brach for updating version information in
`./sdk/src/version.cc`.
```sh
git checkout -b update_version_${tag} master
```
2: Run the pre-commit script to update the version:
```sh
./buildscripts/pre-commit
```
3: Check if any changes made since last release broke ABI compatibility. If yes,
update `OPENTELEMETRY_ABI_VERSION_NO` in
[version.h](api/include/opentelemetry/version.h).
4: Push the changes to upstream and create a Pull Request on GitHub.
5: Once changes are merged, move the tag created earlier to the new commit hash
from step 4.
```sh
git tag -f <previous-tag> <new-commit-hash>
git push --tags --force
```
## Release
Finally create a Release for the new `<new-tag>` on GitHub. The release body
should include all the release notes from the Changelog for this release.
## Post Release
Update the OpenTelemetry.io document
[here](https://github.com/open-telemetry/opentelemetry.io/tree/main/content/en/docs/instrumentation/cpp)
by sending a Pull Request.

View file

@ -0,0 +1,107 @@
# Versioning
This document describes the versioning policy for this repository.
## Goals
### API and SDK Compatibility
Once the API for a given signal (spans, logs, metrics, baggage) has been
officially released, that API module will function with any SDK that has the
same MAJOR version and equal or greater MINOR or PATCH version. For example,
application compiled with API v1.1 is compatible with SDK v1.1.2, v1.2.0, etc.
For example, libraries that are instrumented with `opentelemetry 1.0.1` will
function in applications using `opentelemetry 1.11.33` or `opentelemetry 1.3.4`,
buy may not work in applications using `opentelemetry 2.0.0`.
### ABI Stability
Refer to the [ABI Policy](./docs/abi-policy.md) for more details. To summarise:
* The API is header only, and uses ABI compliant interfaces. However, ABI
stability is not guaranteed for SDK.
* In case of ABI breaking changes, a new `inline namespace` version will be
introduced, and the existing linked applications can continue using the older
version unless they relink with newer version.
## Release Policy
* Release versions will follow [SemVer 2.0](https://semver.org/).
* Only a single source package containing the API, SDK, and exporters which are
required by the specification would be released. All these components are
always versioned and released together. For example, any changes in one of the
exporter would result in version update of the entire source package even
though there is no changes in API, SDK and other exporters.
* Experimental releases: New (unstable) telemetry signals and features will be
introduced behind feature flag protected by a preprocessor macro.
```cpp
#ifdef FEATURE_FLAG
<metrics api/sdk definitions>
#endif
```
As we deliver the package in source form, and the user is responsible to build
it for their platform, the user must be aware of these feature flags
(documented in the [CHANGELOG.md](CHANGELOG.md) file). The user must enable
them explicitly through their build system (CMake, Bazel or others) to use any
preview features.
The guidelines in creating feature flag would be:
* Naming:
* `ENABLE_<SIGNAL>_PREVIEW` : For experimental release of signal api/sdks
eg, `METRICS_PREVIEW`, `LOGS_PREVIEW`,
* `ENABLE_<SIGNAL>_<FEATURE_NAME>_PREVIEW` : For experimental release for
any feature within stable signal. For example, `TRACING_JAEGER_PREVIEW` to
release the experimental Jaeger exporter for tracing.
* Cleanup: It is good practice to keep feature-flags as shortlived as
possible. And, also important to keep the number of them low. They should be
used such that it is easy to remove/cleanup them once the experimental
feature is stable.
* New signals will be stabilized via a **minor version bump**, and are not
allowed to break existing stable interfaces. Feature flags will be removed
once we have a stable implementation for the signal.
* As an exception, small experimental features in otherwise stable
signals/components mayn't necessarily be released under feature flag. These
would be flagged as experimental by adding a `NOTE` in it's header file -
either at the beginning of file, or as the comment for the experimental API
methods. Also, if the complete header is experimental, it would be prefixed as
`experimental_`. As an example, the semantic conventions for trace signal is
experimental at the time of the writing and is within
`experimental_semantic_conventions.h`
* Code under the "*::detail" namespace implements internal details, and is NOT
part of public interface. Also, any API not documented in the [public
documentation](https://opentelemetry-cpp.readthedocs.io/en/latest/) is NOT
part of the public interface.
* GitHub releases will be made for all released versions.
## Example Versioning Lifecycle
Purely for illustration purposes, not intended to represent actual releases:
* v0.0.1 release:
* Contains experimental API and SDK of trace (without feature flag)
* No API and SDK of logging and metrics available
* v1.0.0-rc1 release:
* Pre-release, no API/ABI guarantees, but more stable than alpha/beta.
* Contains pre-release API and SDK of trace, baggage and resource
* experimental metrics and logging API/SDK behind feature flag
* v1.0.0: ( with traces )
* Contains stable API and SDK of trace, baggage and resource
* experimental metrics and logging API/SDK behind feature flag
* v1.5.0 release (with metrics)
* Contains stable API and SDK of metrics, trace, baggage, resource.
* experimental logging API/SDK behind feature flag
* v1.10.0 release (with logging)
* Contains stable API and SDK of logging, metrics, trace, baggage, resource.
### Before moving to version 1.0.0
* Major version zero (0.y.z) is for initial development. Anything MAY change at
any time. The public API SHOULD NOT be considered stable.

View file

@ -0,0 +1,23 @@
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
workspace(name = "io_opentelemetry_cpp")
# Load our direct dependencies.
load("//bazel:repository.bzl", "opentelemetry_cpp_deps")
opentelemetry_cpp_deps()
load("//bazel:extra_deps.bzl", "opentelemetry_extra_deps")
opentelemetry_extra_deps()
# Load gRPC dependencies after load.
load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps")
grpc_deps()
# Load extra gRPC dependencies due to https://github.com/grpc/grpc/issues/20511
load("@com_github_grpc_grpc//bazel:grpc_extra_deps.bzl", "grpc_extra_deps")
grpc_extra_deps()

View file

@ -0,0 +1,4 @@
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
# Disables the default WORKSPACE when using bzlmod

View file

@ -0,0 +1,81 @@
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag", "int_flag", "string_flag")
package(default_visibility = ["//visibility:public"])
CPP_STDLIBS = [
"none",
"best",
"2014",
"2017",
"2020",
"2023",
]
string_flag(
name = "with_cxx_stdlib",
build_setting_default = "best",
values = CPP_STDLIBS,
)
cc_library(
name = "api",
hdrs = glob(["include/**/*.h"]),
defines = select({
":set_cxx_stdlib_none": [],
### automatic selection
":set_cxx_stdlib_best": ["OPENTELEMETRY_STL_VERSION=(__cplusplus/100)"],
# See https://learn.microsoft.com/en-us/cpp/build/reference/zc-cplusplus
":set_cxx_stdlib_best_and_msvc": ["OPENTELEMETRY_STL_VERSION=(_MSVC_LANG/100)"],
### manual selection
":set_cxx_stdlib_2014": ["OPENTELEMETRY_STL_VERSION=2014"],
":set_cxx_stdlib_2017": ["OPENTELEMETRY_STL_VERSION=2017"],
":set_cxx_stdlib_2020": ["OPENTELEMETRY_STL_VERSION=2020"],
":set_cxx_stdlib_2023": ["OPENTELEMETRY_STL_VERSION=2023"],
"//conditions:default": [],
}) + select({
":abi_version_no_1": ["OPENTELEMETRY_ABI_VERSION_NO=1"],
":abi_version_no_2": ["OPENTELEMETRY_ABI_VERSION_NO=2"],
}),
strip_include_prefix = "include",
tags = ["api"],
deps = [
"@com_google_absl//absl/base",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/types:variant",
],
)
[config_setting(
name = "set_cxx_stdlib_%s" % v,
flag_values = {":with_cxx_stdlib": v},
) for v in CPP_STDLIBS]
config_setting(
name = "set_cxx_stdlib_best_and_msvc",
constraint_values = ["@bazel_tools//tools/cpp:msvc"],
flag_values = {":with_cxx_stdlib": "best"},
)
bool_flag(
name = "with_abseil",
build_setting_default = False,
deprecation = "The value of this flag is ignored. Bazel builds always depend on Abseil for its pre-adopted `std::` types. You should remove this flag from your build command.",
)
int_flag(
name = "abi_version_no",
build_setting_default = 1,
)
config_setting(
name = "abi_version_no_1",
flag_values = {":abi_version_no": "1"},
)
config_setting(
name = "abi_version_no_2",
flag_values = {":abi_version_no": "2"},
)

View file

@ -0,0 +1,140 @@
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
add_library(opentelemetry_api INTERFACE)
target_include_directories(
opentelemetry_api
INTERFACE "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>"
"$<INSTALL_INTERFACE:include>")
set_target_properties(opentelemetry_api PROPERTIES EXPORT_NAME api)
otel_add_component(
COMPONENT
api
TARGETS
opentelemetry_api
FILES_DIRECTORY
"include/opentelemetry"
FILES_DESTINATION
"include"
FILES_MATCHING
PATTERN
"*.h")
if(OPENTELEMETRY_INSTALL)
unset(TARGET_DEPS)
endif()
if(BUILD_TESTING)
add_subdirectory(test)
endif()
if(WITH_NO_DEPRECATED_CODE)
target_compile_definitions(opentelemetry_api
INTERFACE OPENTELEMETRY_NO_DEPRECATED_CODE)
endif()
if(WITH_STL STREQUAL "OFF")
message(STATUS "Building WITH_STL=OFF")
elseif(WITH_STL STREQUAL "CXX11")
message(STATUS "Building WITH_STL=CXX11")
target_compile_definitions(opentelemetry_api
INTERFACE OPENTELEMETRY_STL_VERSION=2011)
elseif(WITH_STL STREQUAL "CXX14")
message(STATUS "Building WITH_STL=CXX14")
target_compile_definitions(opentelemetry_api
INTERFACE OPENTELEMETRY_STL_VERSION=2014)
elseif(WITH_STL STREQUAL "CXX17")
message(STATUS "Building WITH_STL=CXX17")
target_compile_definitions(opentelemetry_api
INTERFACE OPENTELEMETRY_STL_VERSION=2017)
elseif(WITH_STL STREQUAL "CXX20")
message(STATUS "Building WITH_STL=CXX20")
target_compile_definitions(opentelemetry_api
INTERFACE OPENTELEMETRY_STL_VERSION=2020)
elseif(WITH_STL STREQUAL "CXX23")
message(STATUS "Building WITH_STL=CXX23")
target_compile_definitions(opentelemetry_api
INTERFACE OPENTELEMETRY_STL_VERSION=2023)
elseif(WITH_STL STREQUAL "ON")
message(STATUS "Building WITH_STL=ON")
# "ON" corresponds to "CXX23" at this time.
target_compile_definitions(opentelemetry_api
INTERFACE OPENTELEMETRY_STL_VERSION=2023)
else()
message(
FATAL_ERROR "WITH_STL must be ON, OFF, CXX11, CXX14, CXX17, CXX20 or CXX23")
endif()
if(WITH_GSL)
target_compile_definitions(opentelemetry_api INTERFACE HAVE_GSL)
# Guidelines Support Library path. Used if we are not on not get C++20.
#
find_package(Microsoft.GSL QUIET)
if(TARGET Microsoft.GSL::GSL)
target_link_libraries(opentelemetry_api INTERFACE Microsoft.GSL::GSL)
list(APPEND TARGET_DEPS "gsl")
else()
set(GSL_DIR third_party/ms-gsl)
target_include_directories(
opentelemetry_api INTERFACE "$<BUILD_INTERFACE:${GSL_DIR}/include>")
endif()
endif()
if(WITH_NO_GETENV)
target_compile_definitions(opentelemetry_api INTERFACE NO_GETENV)
endif()
if(WIN32)
if(WITH_ETW)
target_compile_definitions(opentelemetry_api INTERFACE HAVE_MSGPACK)
endif()
endif()
if(WITH_ASYNC_EXPORT_PREVIEW)
target_compile_definitions(opentelemetry_api INTERFACE ENABLE_ASYNC_EXPORT)
endif()
target_compile_definitions(
opentelemetry_api
INTERFACE OPENTELEMETRY_ABI_VERSION_NO=${OPENTELEMETRY_ABI_VERSION_NO})
if(WITH_OTLP_RETRY_PREVIEW)
target_compile_definitions(opentelemetry_api
INTERFACE ENABLE_OTLP_RETRY_PREVIEW)
endif()
if(WITH_OTLP_GRPC_SSL_MTLS_PREVIEW)
target_compile_definitions(opentelemetry_api
INTERFACE ENABLE_OTLP_GRPC_SSL_MTLS_PREVIEW)
endif()
if(WITH_METRICS_EXEMPLAR_PREVIEW)
target_compile_definitions(opentelemetry_api
INTERFACE ENABLE_METRICS_EXEMPLAR_PREVIEW)
endif()
if(WITH_THREAD_INSTRUMENTATION_PREVIEW)
target_compile_definitions(opentelemetry_api
INTERFACE ENABLE_THREAD_INSTRUMENTATION_PREVIEW)
endif()
if(WITH_OTLP_HTTP_COMPRESSION)
target_compile_definitions(opentelemetry_api
INTERFACE ENABLE_OTLP_COMPRESSION_PREVIEW)
endif()
if(APPLE)
target_link_libraries(opentelemetry_api INTERFACE "-framework CoreFoundation")
endif()
include(${PROJECT_SOURCE_DIR}/cmake/pkgconfig.cmake)
if(OPENTELEMETRY_INSTALL)
opentelemetry_add_pkgconfig(
api "OpenTelemetry API"
"A header-only library to support instrumentation with OpenTelemetry."
"${TARGET_DEPS}")
endif()

View file

@ -0,0 +1,299 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <cctype>
#include "opentelemetry/common/kv_properties.h"
#include "opentelemetry/common/macros.h"
#include "opentelemetry/nostd/shared_ptr.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace baggage
{
class OPENTELEMETRY_EXPORT Baggage
{
public:
static constexpr size_t kMaxKeyValuePairs = 180;
static constexpr size_t kMaxKeyValueSize = 4096;
static constexpr size_t kMaxSize = 8192;
static constexpr char kKeyValueSeparator = '=';
static constexpr char kMembersSeparator = ',';
static constexpr char kMetadataSeparator = ';';
Baggage() noexcept : kv_properties_(new common::KeyValueProperties()) {}
Baggage(size_t size) noexcept : kv_properties_(new common::KeyValueProperties(size)) {}
template <class T>
Baggage(const T &keys_and_values) noexcept
: kv_properties_(new common::KeyValueProperties(keys_and_values))
{}
OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr<Baggage> GetDefault()
{
static nostd::shared_ptr<Baggage> baggage{new Baggage()};
return baggage;
}
/* Get value for key in the baggage
@returns true if key is found, false otherwise
*/
bool GetValue(nostd::string_view key, std::string &value) const noexcept
{
return kv_properties_->GetValue(key, value);
}
/* Returns shared_ptr of new baggage object which contains new key-value pair. If key or value is
invalid, copy of current baggage is returned
*/
nostd::shared_ptr<Baggage> Set(const nostd::string_view &key,
const nostd::string_view &value) noexcept
{
nostd::shared_ptr<Baggage> baggage(new Baggage(kv_properties_->Size() + 1));
const bool valid_kv = IsValidKey(key) && IsValidValue(value);
if (valid_kv)
{
baggage->kv_properties_->AddEntry(key, value);
}
// add rest of the fields.
kv_properties_->GetAllEntries(
[&baggage, &key, &valid_kv](nostd::string_view e_key, nostd::string_view e_value) {
// if key or value was not valid, add all the entries. Add only remaining entries
// otherwise.
if (!valid_kv || key != e_key)
{
baggage->kv_properties_->AddEntry(e_key, e_value);
}
return true;
});
return baggage;
}
// @return all key-values entries by repeatedly invoking the function reference passed as argument
// for each entry
bool GetAllEntries(
nostd::function_ref<bool(nostd::string_view, nostd::string_view)> callback) const noexcept
{
return kv_properties_->GetAllEntries(callback);
}
// delete key from the baggage if it exists. Returns shared_ptr of new baggage object.
// if key does not exist, copy of current baggage is returned.
// Validity of key is not checked as invalid keys should never be populated in baggage in the
// first place.
nostd::shared_ptr<Baggage> Delete(nostd::string_view key) noexcept
{
// keeping size of baggage same as key might not be found in it
nostd::shared_ptr<Baggage> baggage(new Baggage(kv_properties_->Size()));
kv_properties_->GetAllEntries(
[&baggage, &key](nostd::string_view e_key, nostd::string_view e_value) {
if (key != e_key)
baggage->kv_properties_->AddEntry(e_key, e_value);
return true;
});
return baggage;
}
// Returns shared_ptr of baggage after extracting key-value pairs from header
static nostd::shared_ptr<Baggage> FromHeader(nostd::string_view header) noexcept
{
if (header.size() > kMaxSize)
{
// header size exceeds maximum threshold, return empty baggage
return GetDefault();
}
common::KeyValueStringTokenizer kv_str_tokenizer(header);
size_t cnt = kv_str_tokenizer.NumTokens(); // upper bound on number of kv pairs
if (cnt > kMaxKeyValuePairs)
{
cnt = kMaxKeyValuePairs;
}
nostd::shared_ptr<Baggage> baggage(new Baggage(cnt));
bool kv_valid;
nostd::string_view key, value;
while (kv_str_tokenizer.next(kv_valid, key, value) && baggage->kv_properties_->Size() < cnt)
{
if (!kv_valid || (key.size() + value.size() > kMaxKeyValueSize))
{
// if kv pair is not valid, skip it
continue;
}
// NOTE : metadata is kept as part of value only as it does not have any semantic meaning.
// but, we need to extract it (else Decode on value will return error)
nostd::string_view metadata;
auto metadata_separator = value.find(kMetadataSeparator);
if (metadata_separator != std::string::npos)
{
metadata = value.substr(metadata_separator);
value = value.substr(0, metadata_separator);
}
bool err = 0;
auto key_str = UrlDecode(common::StringUtil::Trim(key), err);
auto value_str = UrlDecode(common::StringUtil::Trim(value), err);
if (err == false && IsValidKey(key_str) && IsValidValue(value_str))
{
if (!metadata.empty())
{
value_str.append(metadata.data(), metadata.size());
}
baggage->kv_properties_->AddEntry(key_str, value_str);
}
}
return baggage;
}
// Creates string from baggage object.
std::string ToHeader() const noexcept
{
std::string header_s;
bool first = true;
kv_properties_->GetAllEntries([&](nostd::string_view key, nostd::string_view value) {
if (!first)
{
header_s.push_back(kMembersSeparator);
}
else
{
first = false;
}
header_s.append(UrlEncode(key));
header_s.push_back(kKeyValueSeparator);
// extracting metadata from value. We do not encode metadata
auto metadata_separator = value.find(kMetadataSeparator);
if (metadata_separator != std::string::npos)
{
header_s.append(UrlEncode(value.substr(0, metadata_separator)));
auto metadata = value.substr(metadata_separator);
header_s.append(std::string(metadata.data(), metadata.size()));
}
else
{
header_s.append(UrlEncode(value));
}
return true;
});
return header_s;
}
private:
static bool IsPrintableString(nostd::string_view str)
{
for (const auto ch : str)
{
if (ch < ' ' || ch > '~')
{
return false;
}
}
return true;
}
static bool IsValidKey(nostd::string_view key) { return key.size() && IsPrintableString(key); }
static bool IsValidValue(nostd::string_view value) { return IsPrintableString(value); }
// Uri encode key value pairs before injecting into header
// Implementation inspired from : https://golang.org/src/net/url/url.go?s=7851:7884#L264
static std::string UrlEncode(nostd::string_view str)
{
auto to_hex = [](char c) -> char {
static const char *hex = "0123456789ABCDEF";
return hex[c & 15];
};
std::string ret;
for (auto c : str)
{
if (std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~')
{
ret.push_back(c);
}
else if (c == ' ')
{
ret.push_back('+');
}
else
{
ret.push_back('%');
ret.push_back(to_hex(c >> 4));
ret.push_back(to_hex(c & 15));
}
}
return ret;
}
// Uri decode key value pairs after extracting from header
static std::string UrlDecode(nostd::string_view str, bool &err)
{
auto IsHex = [](char c) {
return std::isdigit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
};
auto from_hex = [](char c) -> char {
// c - '0' produces integer type which could trigger error/warning when casting to char,
// but the cast is safe here.
return static_cast<char>(std::isdigit(c) ? c - '0' : std::toupper(c) - 'A' + 10);
};
std::string ret;
for (size_t i = 0; i < str.size(); i++)
{
if (str[i] == '%')
{
if (i + 2 >= str.size() || !IsHex(str[i + 1]) || !IsHex(str[i + 2]))
{
err = 1;
return "";
}
ret.push_back(from_hex(str[i + 1]) << 4 | from_hex(str[i + 2]));
i += 2;
}
else if (str[i] == '+')
{
ret.push_back(' ');
}
else if (std::isalnum(str[i]) || str[i] == '-' || str[i] == '_' || str[i] == '.' ||
str[i] == '~')
{
ret.push_back(str[i]);
}
else
{
err = 1;
return "";
}
}
return ret;
}
private:
// Store entries in a C-style array to avoid using std::array or std::vector.
nostd::unique_ptr<common::KeyValueProperties> kv_properties_;
};
} // namespace baggage
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,36 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "opentelemetry/baggage/baggage.h"
#include "opentelemetry/context/context.h"
#include "opentelemetry/nostd/shared_ptr.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace baggage
{
static const std::string kBaggageHeader = "baggage";
inline nostd::shared_ptr<Baggage> GetBaggage(const context::Context &context) noexcept
{
context::ContextValue context_value = context.GetValue(kBaggageHeader);
if (nostd::holds_alternative<nostd::shared_ptr<Baggage>>(context_value))
{
return nostd::get<nostd::shared_ptr<Baggage>>(context_value);
}
static nostd::shared_ptr<Baggage> empty_baggage{new Baggage()};
return empty_baggage;
}
inline context::Context SetBaggage(context::Context &context,
const nostd::shared_ptr<Baggage> &baggage) noexcept
{
return context.SetValue(kBaggageHeader, baggage);
}
} // namespace baggage
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,60 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <memory>
#include <string>
#include "opentelemetry/baggage/baggage.h"
#include "opentelemetry/baggage/baggage_context.h"
#include "opentelemetry/context/context.h"
#include "opentelemetry/context/propagation/text_map_propagator.h"
#include "opentelemetry/nostd/function_ref.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace baggage
{
namespace propagation
{
class BaggagePropagator : public context::propagation::TextMapPropagator
{
public:
void Inject(context::propagation::TextMapCarrier &carrier,
const context::Context &context) noexcept override
{
auto baggage = baggage::GetBaggage(context);
auto header = baggage->ToHeader();
if (header.size())
{
carrier.Set(kBaggageHeader, header);
}
}
context::Context Extract(const context::propagation::TextMapCarrier &carrier,
context::Context &context) noexcept override
{
nostd::string_view baggage_str = carrier.Get(baggage::kBaggageHeader);
auto baggage = baggage::Baggage::FromHeader(baggage_str);
if (baggage->ToHeader().size())
{
return baggage::SetBaggage(context, baggage);
}
else
{
return context;
}
}
bool Fields(nostd::function_ref<bool(nostd::string_view)> callback) const noexcept override
{
return callback(kBaggageHeader);
}
};
} // namespace propagation
} // namespace baggage
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,82 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <cstdint>
#include "opentelemetry/nostd/span.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/nostd/variant.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace common
{
/// OpenTelemetry signals can be enriched by adding attributes. The
/// \c AttributeValue type is defined as a variant of all attribute value
/// types the OpenTelemetry C++ API supports.
///
/// The following attribute value types are supported by the OpenTelemetry
/// specification:
/// - Primitive types: string, boolean, double precision floating point
/// (IEEE 754-1985) or signed 64 bit integer.
/// - Homogenous arrays of primitive type values.
///
/// \warning
/// \parblock The OpenTelemetry C++ API currently supports several attribute
/// value types that are not covered by the OpenTelemetry specification:
/// - \c uint64_t
/// - \c nostd::span<const uint64_t>
/// - \c nostd::span<uint8_t>
///
/// Those types are reserved for future use and currently should not be
/// used. There are no guarantees around how those values are handled by
/// exporters.
/// \endparblock
using AttributeValue =
nostd::variant<bool,
int32_t,
int64_t,
uint32_t,
double,
const char *,
nostd::string_view,
nostd::span<const bool>,
nostd::span<const int32_t>,
nostd::span<const int64_t>,
nostd::span<const uint32_t>,
nostd::span<const double>,
nostd::span<const nostd::string_view>,
// Not currently supported by the specification, but reserved for future use.
// Added to provide support for all primitive C++ types.
uint64_t,
// Not currently supported by the specification, but reserved for future use.
// Added to provide support for all primitive C++ types.
nostd::span<const uint64_t>,
// Not currently supported by the specification, but reserved for future use.
// See https://github.com/open-telemetry/opentelemetry-specification/issues/780
nostd::span<const uint8_t>>;
enum AttributeType
{
kTypeBool,
kTypeInt,
kTypeInt64,
kTypeUInt,
kTypeDouble,
kTypeCString,
kTypeString,
kTypeSpanBool,
kTypeSpanInt,
kTypeSpanInt64,
kTypeSpanUInt,
kTypeSpanDouble,
kTypeSpanString,
kTypeUInt64,
kTypeSpanUInt64,
kTypeSpanByte
};
} // namespace common
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,64 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "opentelemetry/common/attribute_value.h"
#include "opentelemetry/nostd/function_ref.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace common
{
/**
* Supports internal iteration over a collection of key-value pairs.
*/
class KeyValueIterable
{
public:
virtual ~KeyValueIterable() = default;
/**
* Iterate over key-value pairs
* @param callback a callback to invoke for each key-value. If the callback returns false,
* the iteration is aborted.
* @return true if every key-value pair was iterated over
*/
virtual bool ForEachKeyValue(nostd::function_ref<bool(nostd::string_view, common::AttributeValue)>
callback) const noexcept = 0;
/**
* @return the number of key-value pairs
*/
virtual size_t size() const noexcept = 0;
};
/**
* Supports internal iteration over a collection of key-value pairs.
*/
class NoopKeyValueIterable : public KeyValueIterable
{
public:
~NoopKeyValueIterable() override = default;
/**
* Iterate over key-value pairs
* @param callback a callback to invoke for each key-value. If the callback returns false,
* the iteration is aborted.
* @return true if every key-value pair was iterated over
*/
bool ForEachKeyValue(
nostd::function_ref<bool(nostd::string_view, common::AttributeValue)>) const noexcept override
{
return true;
}
/**
* @return the number of key-value pairs
*/
size_t size() const noexcept override { return 0; }
};
} // namespace common
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,146 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <stddef.h>
#include <initializer_list>
#include <iterator>
#include <type_traits>
#include <utility>
#include <vector>
#include "opentelemetry/common/attribute_value.h"
#include "opentelemetry/common/key_value_iterable.h"
#include "opentelemetry/nostd/function_ref.h"
#include "opentelemetry/nostd/span.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/nostd/type_traits.h"
#include "opentelemetry/nostd/utility.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace common
{
// NOTE - code within `detail` namespace implements internal details, and not part
// of the public interface.
namespace detail
{
inline void take_key_value(nostd::string_view, common::AttributeValue) {}
template <class T>
auto is_key_value_iterable_impl(T iterable)
-> decltype(take_key_value(std::begin(iterable)->first, std::begin(iterable)->second),
nostd::size(iterable),
std::true_type{});
std::false_type is_key_value_iterable_impl(...);
template <class T>
struct is_key_value_iterable
{
static const bool value = decltype(detail::is_key_value_iterable_impl(std::declval<T>()))::value;
};
} // namespace detail
/**
* @brief Container for key-value pairs that can transform every value in it to one of types
* listed in common::AttributeValue. It may contain value types that are not directly map'able
* to primitive value types. In that case the `ForEachKeyValue` method acts as a transform to
* convert the value type to one listed under AtributeValue (bool, int32_t, int64_t, uint32_t,
* uint64_t, double, nostd::string_view, or arrays of primite types). For example, if UUID,
* GUID, or UTF-16 string type is passed as one of values stored inside this container, the
* container itself may provide a custom implementation of `ForEachKeyValue` to transform the
* 'non-standard' type to one of the standard types.
*/
template <class T>
class KeyValueIterableView final : public KeyValueIterable
{
public:
explicit KeyValueIterableView(const T &container) noexcept : container_{&container} {}
// KeyValueIterable
bool ForEachKeyValue(nostd::function_ref<bool(nostd::string_view, common::AttributeValue)>
callback) const noexcept override
{
auto iter = std::begin(*container_);
auto last = std::end(*container_);
for (; iter != last; ++iter)
{
if (!callback(iter->first, iter->second))
{
return false;
}
}
return true;
}
size_t size() const noexcept override { return nostd::size(*container_); }
private:
const T *container_;
};
template <class T, nostd::enable_if_t<detail::is_key_value_iterable<T>::value> * = nullptr>
KeyValueIterableView<T> MakeKeyValueIterableView(const T &container) noexcept
{
return KeyValueIterableView<T>(container);
}
/**
* Utility function to help to make a attribute view from initializer_list
*
* @param attributes
* @return nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>
*/
inline static nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>
MakeAttributes(std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>
attributes) noexcept
{
return nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
attributes.begin(), attributes.end()};
}
/**
* Utility function to help to make a attribute view from a span
*
* @param attributes
* @return nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>
*/
inline static nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>
MakeAttributes(
nostd::span<const std::pair<nostd::string_view, common::AttributeValue>> attributes) noexcept
{
return attributes;
}
/**
* Utility function to help to make a attribute view from a KeyValueIterable
*
* @param attributes
* @return common::KeyValueIterable
*/
inline static const common::KeyValueIterable &MakeAttributes(
const common::KeyValueIterable &attributes) noexcept
{
return attributes;
}
/**
* Utility function to help to make a attribute view from a key-value iterable object
*
* @param attributes
* @return nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>
*/
template <
class ArgumentType,
nostd::enable_if_t<common::detail::is_key_value_iterable<ArgumentType>::value> * = nullptr>
inline static common::KeyValueIterableView<ArgumentType> MakeAttributes(
const ArgumentType &arg) noexcept
{
return common::KeyValueIterableView<ArgumentType>(arg);
}
} // namespace common
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,272 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "opentelemetry/common/key_value_iterable_view.h"
#include "opentelemetry/common/string_util.h"
#include "opentelemetry/nostd/function_ref.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/nostd/unique_ptr.h"
#include "opentelemetry/version.h"
#include <cstring>
#include <string>
#include <type_traits>
OPENTELEMETRY_BEGIN_NAMESPACE
namespace common
{
// Constructor parameter for KeyValueStringTokenizer
struct KeyValueStringTokenizerOptions
{
char member_separator = ',';
char key_value_separator = '=';
bool ignore_empty_members = true;
};
// Tokenizer for key-value headers
class KeyValueStringTokenizer
{
public:
KeyValueStringTokenizer(
nostd::string_view str,
const KeyValueStringTokenizerOptions &opts = KeyValueStringTokenizerOptions()) noexcept
: str_(str), opts_(opts), index_(0)
{}
static nostd::string_view GetDefaultKeyOrValue()
{
static std::string default_str = "";
return default_str;
}
// Returns next key value in the string header
// @param valid_kv : if the found kv pair is valid or not
// @param key : key in kv pair
// @param key : value in kv pair
// @returns true if next kv pair was found, false otherwise.
bool next(bool &valid_kv, nostd::string_view &key, nostd::string_view &value) noexcept
{
valid_kv = true;
while (index_ < str_.size())
{
bool is_empty_pair = false;
size_t end = str_.find(opts_.member_separator, index_);
if (end == std::string::npos)
{
end = str_.size() - 1;
}
else if (end == index_) // empty pair. do not update end
{
is_empty_pair = true;
}
else
{
end--;
}
auto list_member = StringUtil::Trim(str_, index_, end);
if (list_member.size() == 0 || is_empty_pair)
{
// empty list member
index_ = end + 2 - is_empty_pair;
if (opts_.ignore_empty_members)
{
continue;
}
valid_kv = true;
key = GetDefaultKeyOrValue();
value = GetDefaultKeyOrValue();
return true;
}
auto key_end_pos = list_member.find(opts_.key_value_separator);
if (key_end_pos == std::string::npos)
{
// invalid member
valid_kv = false;
}
else
{
key = list_member.substr(0, key_end_pos);
value = list_member.substr(key_end_pos + 1);
}
index_ = end + 2;
return true;
}
// no more entries remaining
return false;
}
// Returns total number of tokens in header string
size_t NumTokens() const noexcept
{
size_t cnt = 0, begin = 0;
while (begin < str_.size())
{
++cnt;
size_t end = str_.find(opts_.member_separator, begin);
if (end == std::string::npos)
{
break;
}
begin = end + 1;
}
return cnt;
}
// Resets the iterator
void reset() noexcept { index_ = 0; }
private:
nostd::string_view str_;
KeyValueStringTokenizerOptions opts_;
size_t index_;
};
// Class to store fixed size array of key-value pairs of string type
class KeyValueProperties
{
// Class to store key-value pairs of string types
public:
class Entry
{
public:
Entry() : key_(nullptr), value_(nullptr) {}
// Copy constructor
Entry(const Entry &copy)
{
key_ = CopyStringToPointer(copy.key_.get());
value_ = CopyStringToPointer(copy.value_.get());
}
// Copy assignment operator
Entry &operator=(Entry &other)
{
key_ = CopyStringToPointer(other.key_.get());
value_ = CopyStringToPointer(other.value_.get());
return *this;
}
// Move contructor and assignment operator
Entry(Entry &&other) = default;
Entry &operator=(Entry &&other) = default;
// Creates an Entry for a given key-value pair.
Entry(nostd::string_view key, nostd::string_view value)
{
key_ = CopyStringToPointer(key);
value_ = CopyStringToPointer(value);
}
// Gets the key associated with this entry.
nostd::string_view GetKey() const noexcept { return key_.get(); }
// Gets the value associated with this entry.
nostd::string_view GetValue() const noexcept { return value_.get(); }
// Sets the value for this entry. This overrides the previous value.
void SetValue(nostd::string_view value) noexcept { value_ = CopyStringToPointer(value); }
private:
// Store key and value as raw char pointers to avoid using std::string.
nostd::unique_ptr<const char[]> key_;
nostd::unique_ptr<const char[]> value_;
// Copies string into a buffer and returns a unique_ptr to the buffer.
// This is a workaround for the fact that memcpy doesn't accept a const destination.
nostd::unique_ptr<const char[]> CopyStringToPointer(nostd::string_view str)
{
char *temp = new char[str.size() + 1];
memcpy(temp, str.data(), str.size());
temp[str.size()] = '\0';
return nostd::unique_ptr<const char[]>(temp);
}
};
// Maintain the number of entries in entries_.
size_t num_entries_;
// Max size of allocated array
size_t max_num_entries_;
// Store entries in a C-style array to avoid using std::array or std::vector.
nostd::unique_ptr<Entry[]> entries_;
public:
// Create Key-value list of given size
// @param size : Size of list.
KeyValueProperties(size_t size) noexcept
: num_entries_(0), max_num_entries_(size), entries_(new Entry[size])
{}
// Create Empty Key-Value list
KeyValueProperties() noexcept : num_entries_(0), max_num_entries_(0), entries_(nullptr) {}
template <class T, class = typename std::enable_if<detail::is_key_value_iterable<T>::value>::type>
KeyValueProperties(const T &keys_and_values) noexcept
: num_entries_(0),
max_num_entries_(keys_and_values.size()),
entries_(new Entry[max_num_entries_])
{
for (auto &e : keys_and_values)
{
Entry entry(e.first, e.second);
(entries_.get())[num_entries_++] = std::move(entry);
}
}
// Adds new kv pair into kv properties
void AddEntry(nostd::string_view key, nostd::string_view value) noexcept
{
if (num_entries_ < max_num_entries_)
{
Entry entry(key, value);
(entries_.get())[num_entries_++] = std::move(entry);
}
}
// Returns all kv pair entries
bool GetAllEntries(
nostd::function_ref<bool(nostd::string_view, nostd::string_view)> callback) const noexcept
{
for (size_t i = 0; i < num_entries_; i++)
{
auto &entry = (entries_.get())[i];
if (!callback(entry.GetKey(), entry.GetValue()))
{
return false;
}
}
return true;
}
// Return value for key if exists, return false otherwise
bool GetValue(nostd::string_view key, std::string &value) const noexcept
{
for (size_t i = 0; i < num_entries_; i++)
{
auto &entry = (entries_.get())[i];
if (entry.GetKey() == key)
{
const auto &entry_value = entry.GetValue();
value = std::string(entry_value.data(), entry_value.size());
return true;
}
}
return false;
}
size_t Size() const noexcept { return num_entries_; }
};
} // namespace common
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,523 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
/*
OPENTELEMETRY_HAVE_BUILTIN&OPENTELEMETRY_HAVE_FEATURE
Checks whether the compiler supports a Clang Feature Checking Macro, and if
so, checks whether it supports the provided builtin function "x" where x
is one of the functions noted in
https://clang.llvm.org/docs/LanguageExtensions.html
Note: Use this macro to avoid an extra level of #ifdef __has_builtin check.
http://releases.llvm.org/3.3/tools/clang/docs/LanguageExtensions.html
*/
#if !defined(OPENTELEMETRY_HAVE_BUILTIN)
# ifdef __has_builtin
# define OPENTELEMETRY_HAVE_BUILTIN(x) __has_builtin(x)
# else
# define OPENTELEMETRY_HAVE_BUILTIN(x) 0
# endif
#endif
#if !defined(OPENTELEMETRY_HAVE_FEATURE)
# ifdef __has_feature
# define OPENTELEMETRY_HAVE_FEATURE(f) __has_feature(f)
# else
# define OPENTELEMETRY_HAVE_FEATURE(f) 0
# endif
#endif
/*
has feature
OPENTELEMETRY_HAVE_ATTRIBUTE
A function-like feature checking macro that is a wrapper around
`__has_attribute`, which is defined by GCC 5+ and Clang and evaluates to a
nonzero constant integer if the attribute is supported or 0 if not.
It evaluates to zero if `__has_attribute` is not defined by the compiler.
GCC: https://gcc.gnu.org/gcc-5/changes.html
Clang: https://clang.llvm.org/docs/LanguageExtensions.html
*/
#if !defined(OPENTELEMETRY_HAVE_ATTRIBUTE)
# ifdef __has_attribute
# define OPENTELEMETRY_HAVE_ATTRIBUTE(x) __has_attribute(x)
# else
# define OPENTELEMETRY_HAVE_ATTRIBUTE(x) 0
# endif
#endif
/*
OPENTELEMETRY_HAVE_CPP_ATTRIBUTE
A function-like feature checking macro that accepts C++11 style attributes.
It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6
(https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't
find `__has_cpp_attribute`, will evaluate to 0.
*/
#if !defined(OPENTELEMETRY_HAVE_CPP_ATTRIBUTE)
# if defined(__cplusplus) && defined(__has_cpp_attribute)
// NOTE: requiring __cplusplus above should not be necessary, but
// works around https://bugs.llvm.org/show_bug.cgi?id=23435.
# define OPENTELEMETRY_HAVE_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
# else
# define OPENTELEMETRY_HAVE_CPP_ATTRIBUTE(x) 0
# endif
#endif
/*
Expected usage pattern:
if OPENTELEMETRY_LIKELY_CONDITION (ptr != nullptr)
{
do_something_likely();
} else {
do_something_unlikely();
}
This pattern works with gcc/clang and __builtin_expect(),
as well as with C++20.
It is unclear if __builtin_expect() will be deprecated
in favor of C++20 [[likely]] or not.
OPENTELEMETRY_LIKELY_CONDITION is preferred over OPENTELEMETRY_LIKELY,
to be revisited when C++20 is required.
*/
#if !defined(OPENTELEMETRY_LIKELY_CONDITION) && defined(__cplusplus)
// Only use likely with C++20
# if __cplusplus >= 202002L
// GCC 9 has likely attribute but do not support declare it at the beginning of statement
# if defined(__has_cpp_attribute) && (defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 9)
# if __has_cpp_attribute(likely)
# define OPENTELEMETRY_LIKELY_CONDITION(C) (C) [[likely]]
# endif
# endif
# endif
#endif
#if !defined(OPENTELEMETRY_LIKELY_CONDITION) && (defined(__clang__) || defined(__GNUC__))
// Only use if supported by the compiler
# define OPENTELEMETRY_LIKELY_CONDITION(C) (__builtin_expect(!!(C), true))
#endif
#ifndef OPENTELEMETRY_LIKELY_CONDITION
// Do not use likely annotations
# define OPENTELEMETRY_LIKELY_CONDITION(C) (C)
#endif
#if !defined(OPENTELEMETRY_UNLIKELY_CONDITION) && defined(__cplusplus)
// Only use unlikely with C++20
# if __cplusplus >= 202002L
// GCC 9 has unlikely attribute but do not support declare it at the beginning of statement
# if defined(__has_cpp_attribute) && (defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 9)
# if __has_cpp_attribute(unlikely)
# define OPENTELEMETRY_UNLIKELY_CONDITION(C) (C) [[unlikely]]
# endif
# endif
# endif
#endif
#if !defined(OPENTELEMETRY_UNLIKELY_CONDITION) && (defined(__clang__) || defined(__GNUC__))
// Only use if supported by the compiler
# define OPENTELEMETRY_UNLIKELY_CONDITION(C) (__builtin_expect(!!(C), false))
#endif
#ifndef OPENTELEMETRY_UNLIKELY_CONDITION
// Do not use unlikely annotations
# define OPENTELEMETRY_UNLIKELY_CONDITION(C) (C)
#endif
/*
Expected usage pattern:
if (ptr != nullptr)
OPENTELEMETRY_LIKELY
{
do_something_likely();
} else {
do_something_unlikely();
}
This pattern works starting with C++20.
See https://en.cppreference.com/w/cpp/language/attributes/likely
Please use OPENTELEMETRY_LIKELY_CONDITION instead for now.
*/
#if !defined(OPENTELEMETRY_LIKELY) && defined(__cplusplus)
// Only use likely with C++20
# if __cplusplus >= 202002L
// GCC 9 has likely attribute but do not support declare it at the beginning of statement
# if defined(__has_cpp_attribute) && (defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 9)
# if __has_cpp_attribute(likely)
# define OPENTELEMETRY_LIKELY [[likely]]
# endif
# endif
# endif
#endif
#ifndef OPENTELEMETRY_LIKELY
# define OPENTELEMETRY_LIKELY
#endif
#if !defined(OPENTELEMETRY_UNLIKELY) && defined(__cplusplus)
// Only use unlikely with C++20
# if __cplusplus >= 202002L
// GCC 9 has unlikely attribute but do not support declare it at the beginning of statement
# if defined(__has_cpp_attribute) && (defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 9)
# if __has_cpp_attribute(unlikely)
# define OPENTELEMETRY_UNLIKELY [[unlikely]]
# endif
# endif
# endif
#endif
#ifndef OPENTELEMETRY_UNLIKELY
# define OPENTELEMETRY_UNLIKELY
#endif
/// \brief Declare variable as maybe unused
/// usage:
/// OPENTELEMETRY_MAYBE_UNUSED int a;
/// class OPENTELEMETRY_MAYBE_UNUSED a;
/// OPENTELEMETRY_MAYBE_UNUSED int a();
///
#if defined(__cplusplus) && __cplusplus >= 201703L
# define OPENTELEMETRY_MAYBE_UNUSED [[maybe_unused]]
#elif defined(__clang__)
# define OPENTELEMETRY_MAYBE_UNUSED __attribute__((unused))
#elif defined(__GNUC__) && ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)))
# define OPENTELEMETRY_MAYBE_UNUSED __attribute__((unused))
#elif (defined(_MSC_VER) && _MSC_VER >= 1910) && (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
# define OPENTELEMETRY_MAYBE_UNUSED [[maybe_unused]]
#else
# define OPENTELEMETRY_MAYBE_UNUSED
#endif
#ifndef OPENTELEMETRY_RTTI_ENABLED
# if defined(__clang__)
# if __has_feature(cxx_rtti)
# define OPENTELEMETRY_RTTI_ENABLED
# endif
# elif defined(__GNUG__)
# if defined(__GXX_RTTI)
# define OPENTELEMETRY_RTTI_ENABLED
# endif
# elif defined(_MSC_VER)
# if defined(_CPPRTTI)
# define OPENTELEMETRY_RTTI_ENABLED
# endif
# endif
#endif
#if defined(__cplusplus) && __cplusplus >= 201402L
# define OPENTELEMETRY_DEPRECATED [[deprecated]]
#elif defined(__clang__)
# define OPENTELEMETRY_DEPRECATED __attribute__((deprecated))
#elif defined(__GNUC__)
# define OPENTELEMETRY_DEPRECATED __attribute__((deprecated))
#elif defined(_MSC_VER)
# if _MSC_VER >= 1910 && defined(_MSVC_LANG) && _MSVC_LANG >= 201703L
# define OPENTELEMETRY_DEPRECATED [[deprecated]]
# else
# define OPENTELEMETRY_DEPRECATED __declspec(deprecated)
# endif
#else
# define OPENTELEMETRY_DEPRECATED
#endif
#if defined(__cplusplus) && __cplusplus >= 201402L
# define OPENTELEMETRY_DEPRECATED_MESSAGE(msg) [[deprecated(msg)]]
#elif defined(__clang__)
# define OPENTELEMETRY_DEPRECATED_MESSAGE(msg) __attribute__((deprecated(msg)))
#elif defined(__GNUC__)
# define OPENTELEMETRY_DEPRECATED_MESSAGE(msg) __attribute__((deprecated(msg)))
#elif defined(_MSC_VER)
# if _MSC_VER >= 1910 && defined(_MSVC_LANG) && _MSVC_LANG >= 201703L
# define OPENTELEMETRY_DEPRECATED_MESSAGE(msg) [[deprecated(msg)]]
# else
# define OPENTELEMETRY_DEPRECATED_MESSAGE(msg) __declspec(deprecated(msg))
# endif
#else
# define OPENTELEMETRY_DEPRECATED_MESSAGE(msg)
#endif
// Regex support
#if (__GNUC__ == 4 && (__GNUC_MINOR__ == 8 || __GNUC_MINOR__ == 9))
# define OPENTELEMETRY_HAVE_WORKING_REGEX 0
#else
# define OPENTELEMETRY_HAVE_WORKING_REGEX 1
#endif
/* clang-format off */
/**
@page HEADER_ONLY_SINGLETON Header only singleton.
@section ELF_SINGLETON
For clang and gcc, the desired coding pattern is as follows.
@verbatim
class Foo
{
// (a)
__attribute__((visibility("default")))
// (b)
T& get_singleton()
{
// (c)
static T singleton;
return singleton;
}
};
@endverbatim
(a) is needed when the code is build with
@code -fvisibility="hidden" @endcode
to ensure that all instances of (b) are visible to the linker.
What is duplicated in the binary is @em code, in (b).
The linker will make sure only one instance
of all the (b) methods is used.
(c) is a singleton implemented inside a method.
This is very desirable, because:
- the C++ compiler guarantees that construction
of the variable (c) is thread safe.
- constructors for (c) singletons are executed in code path order,
or not at all if the singleton is never used.
@section OTHER_SINGLETON
For other platforms, header only singletons are not supported at this
point.
@section CODING_PATTERN
The coding pattern to use in the source code is as follows
@verbatim
class Foo
{
OPENTELEMETRY_API_SINGLETON
T& get_singleton()
{
static T singleton;
return singleton;
}
};
@endverbatim
*/
/* clang-format on */
#if defined(__clang__)
# define OPENTELEMETRY_API_SINGLETON __attribute__((visibility("default")))
# define OPENTELEMETRY_LOCAL_SYMBOL __attribute__((visibility("hidden")))
#elif defined(__GNUC__)
# define OPENTELEMETRY_API_SINGLETON __attribute__((visibility("default")))
# define OPENTELEMETRY_LOCAL_SYMBOL __attribute__((visibility("hidden")))
#else
/* Add support for other compilers here. */
# define OPENTELEMETRY_API_SINGLETON
# define OPENTELEMETRY_LOCAL_SYMBOL
#endif
//
// Atomic wrappers based on compiler intrinsics for memory read/write.
// The tailing number is read/write length in bits.
//
// N.B. Compiler intrinsic is used because the usage of C++ standard library is restricted in the
// OpenTelemetry C++ API.
//
#if defined(__GNUC__)
# define OPENTELEMETRY_ATOMIC_READ_8(ptr) __atomic_load_n(ptr, __ATOMIC_SEQ_CST)
# define OPENTELEMETRY_ATOMIC_WRITE_8(ptr, value) __atomic_store_n(ptr, value, __ATOMIC_SEQ_CST)
#elif defined(_MSC_VER)
# include <intrin.h>
# define OPENTELEMETRY_ATOMIC_READ_8(ptr) \
static_cast<uint8_t>(_InterlockedCompareExchange8(reinterpret_cast<char *>(ptr), 0, 0))
# define OPENTELEMETRY_ATOMIC_WRITE_8(ptr, value) \
_InterlockedExchange8(reinterpret_cast<char *>(ptr), static_cast<char>(value))
#else
# error port atomics read/write for the current platform
#endif
/* clang-format on */
//
// The if/elif order matters here. If both OPENTELEMETRY_BUILD_IMPORT_DLL and
// OPENTELEMETRY_BUILD_EXPORT_DLL are defined, the former takes precedence.
//
// TODO: consider define OPENTELEMETRY_EXPORT for cygwin/gcc, see below link.
// https://gcc.gnu.org/wiki/Visibility#How_to_use_the_new_C.2B-.2B-_visibility_support
//
#if defined(_MSC_VER) && defined(OPENTELEMETRY_BUILD_IMPORT_DLL)
# define OPENTELEMETRY_EXPORT __declspec(dllimport)
#elif defined(_MSC_VER) && defined(OPENTELEMETRY_BUILD_EXPORT_DLL)
# define OPENTELEMETRY_EXPORT __declspec(dllexport)
#else
//
// build OpenTelemetry as static library or not on Windows.
//
# define OPENTELEMETRY_EXPORT
#endif
// OPENTELEMETRY_HAVE_EXCEPTIONS
//
// Checks whether the compiler both supports and enables exceptions. Many
// compilers support a "no exceptions" mode that disables exceptions.
//
// Generally, when OPENTELEMETRY_HAVE_EXCEPTIONS is not defined:
//
// * Code using `throw` and `try` may not compile.
// * The `noexcept` specifier will still compile and behave as normal.
// * The `noexcept` operator may still return `false`.
//
// For further details, consult the compiler's documentation.
#ifndef OPENTELEMETRY_HAVE_EXCEPTIONS
# if defined(__clang__) && ((__clang_major__ * 100) + __clang_minor__) < 306
// Clang < 3.6
// http://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html#the-exceptions-macro
# if defined(__EXCEPTIONS) && OPENTELEMETRY_HAVE_FEATURE(cxx_exceptions)
# define OPENTELEMETRY_HAVE_EXCEPTIONS 1
# endif // defined(__EXCEPTIONS) && OPENTELEMETRY_HAVE_FEATURE(cxx_exceptions)
# elif OPENTELEMETRY_HAVE_FEATURE(cxx_exceptions)
# define OPENTELEMETRY_HAVE_EXCEPTIONS 1
// Handle remaining special cases and default to exceptions being supported.
# elif !(defined(__GNUC__) && !defined(__EXCEPTIONS) && !defined(__cpp_exceptions)) && \
!(defined(_MSC_VER) && !defined(_CPPUNWIND))
# define OPENTELEMETRY_HAVE_EXCEPTIONS 1
# endif
#endif
#ifndef OPENTELEMETRY_HAVE_EXCEPTIONS
# define OPENTELEMETRY_HAVE_EXCEPTIONS 0
#endif
/*
OPENTELEMETRY_ATTRIBUTE_LIFETIME_BOUND indicates that a resource owned by a function
parameter or implicit object parameter is retained by the return value of the
annotated function (or, for a parameter of a constructor, in the value of the
constructed object). This attribute causes warnings to be produced if a
temporary object does not live long enough.
When applied to a reference parameter, the referenced object is assumed to be
retained by the return value of the function. When applied to a non-reference
parameter (for example, a pointer or a class type), all temporaries
referenced by the parameter are assumed to be retained by the return value of
the function.
See also the upstream documentation:
https://clang.llvm.org/docs/AttributeReference.html#lifetimebound
*/
#ifndef OPENTELEMETRY_ATTRIBUTE_LIFETIME_BOUND
# if OPENTELEMETRY_HAVE_CPP_ATTRIBUTE(clang::lifetimebound)
# define OPENTELEMETRY_ATTRIBUTE_LIFETIME_BOUND [[clang::lifetimebound]]
# elif OPENTELEMETRY_HAVE_ATTRIBUTE(lifetimebound)
# define OPENTELEMETRY_ATTRIBUTE_LIFETIME_BOUND __attribute__((lifetimebound))
# else
# define OPENTELEMETRY_ATTRIBUTE_LIFETIME_BOUND
# endif
#endif
// OPENTELEMETRY_HAVE_MEMORY_SANITIZER
//
// MemorySanitizer (MSan) is a detector of uninitialized reads. It consists of
// a compiler instrumentation module and a run-time library.
#ifndef OPENTELEMETRY_HAVE_MEMORY_SANITIZER
# if !defined(__native_client__) && OPENTELEMETRY_HAVE_FEATURE(memory_sanitizer)
# define OPENTELEMETRY_HAVE_MEMORY_SANITIZER 1
# else
# define OPENTELEMETRY_HAVE_MEMORY_SANITIZER 0
# endif
#endif
#if OPENTELEMETRY_HAVE_MEMORY_SANITIZER && OPENTELEMETRY_HAVE_ATTRIBUTE(no_sanitize_memory)
# define OPENTELEMETRY_SANITIZER_NO_MEMORY \
__attribute__((no_sanitize_memory)) // __attribute__((no_sanitize("memory")))
#else
# define OPENTELEMETRY_SANITIZER_NO_MEMORY
#endif
// OPENTELEMETRY_HAVE_THREAD_SANITIZER
//
// ThreadSanitizer (TSan) is a fast data race detector.
#ifndef OPENTELEMETRY_HAVE_THREAD_SANITIZER
# if defined(__SANITIZE_THREAD__)
# define OPENTELEMETRY_HAVE_THREAD_SANITIZER 1
# elif OPENTELEMETRY_HAVE_FEATURE(thread_sanitizer)
# define OPENTELEMETRY_HAVE_THREAD_SANITIZER 1
# else
# define OPENTELEMETRY_HAVE_THREAD_SANITIZER 0
# endif
#endif
#if OPENTELEMETRY_HAVE_THREAD_SANITIZER && OPENTELEMETRY_HAVE_ATTRIBUTE(no_sanitize_thread)
# define OPENTELEMETRY_SANITIZER_NO_THREAD \
__attribute__((no_sanitize_thread)) // __attribute__((no_sanitize("thread")))
#else
# define OPENTELEMETRY_SANITIZER_NO_THREAD
#endif
// OPENTELEMETRY_HAVE_ADDRESS_SANITIZER
//
// AddressSanitizer (ASan) is a fast memory error detector.
#ifndef OPENTELEMETRY_HAVE_ADDRESS_SANITIZER
# if defined(__SANITIZE_ADDRESS__)
# define OPENTELEMETRY_HAVE_ADDRESS_SANITIZER 1
# elif OPENTELEMETRY_HAVE_FEATURE(address_sanitizer)
# define OPENTELEMETRY_HAVE_ADDRESS_SANITIZER 1
# else
# define OPENTELEMETRY_HAVE_ADDRESS_SANITIZER 0
# endif
#endif
// OPENTELEMETRY_HAVE_HWADDRESS_SANITIZER
//
// Hardware-Assisted AddressSanitizer (or HWASAN) is even faster than asan
// memory error detector which can use CPU features like ARM TBI, Intel LAM or
// AMD UAI.
#ifndef OPENTELEMETRY_HAVE_HWADDRESS_SANITIZER
# if defined(__SANITIZE_HWADDRESS__)
# define OPENTELEMETRY_HAVE_HWADDRESS_SANITIZER 1
# elif OPENTELEMETRY_HAVE_FEATURE(hwaddress_sanitizer)
# define OPENTELEMETRY_HAVE_HWADDRESS_SANITIZER 1
# else
# define OPENTELEMETRY_HAVE_HWADDRESS_SANITIZER 0
# endif
#endif
#if OPENTELEMETRY_HAVE_ADDRESS_SANITIZER && OPENTELEMETRY_HAVE_ATTRIBUTE(no_sanitize_address)
# define OPENTELEMETRY_SANITIZER_NO_ADDRESS \
__attribute__((no_sanitize_address)) // __attribute__((no_sanitize("address")))
#elif OPENTELEMETRY_HAVE_ADDRESS_SANITIZER && defined(_MSC_VER) && _MSC_VER >= 1928
# define OPENTELEMETRY_SANITIZER_NO_ADDRESS __declspec(no_sanitize_address)
#elif OPENTELEMETRY_HAVE_HWADDRESS_SANITIZER && OPENTELEMETRY_HAVE_ATTRIBUTE(no_sanitize)
# define OPENTELEMETRY_SANITIZER_NO_ADDRESS __attribute__((no_sanitize("hwaddress")))
#else
# define OPENTELEMETRY_SANITIZER_NO_ADDRESS
#endif

View file

@ -0,0 +1,133 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <atomic>
#include <chrono>
#include <thread>
#include "opentelemetry/version.h"
#if defined(_MSC_VER)
# define _WINSOCKAPI_ // stops including winsock.h
# include <windows.h>
#elif defined(__i386__) || defined(__x86_64__)
# if defined(__clang__)
# include <emmintrin.h>
# elif defined(__INTEL_COMPILER)
# include <immintrin.h>
# endif
#endif
OPENTELEMETRY_BEGIN_NAMESPACE
namespace common
{
constexpr int SPINLOCK_FAST_ITERATIONS = 100;
constexpr int SPINLOCK_SLEEP_MS = 1;
/**
* A Mutex which uses atomic flags and spin-locks instead of halting threads.
*
* This mutex uses an incremental back-off strategy with the following phases:
* 1. A tight spin-lock loop (pending: using hardware PAUSE/YIELD instructions)
* 2. A loop where the current thread yields control after checking the lock.
* 3. Issuing a thread-sleep call before starting back in phase 1.
*
* This is meant to give a good balance of perofrmance and CPU consumption in
* practice.
*
* This mutex uses an incremental back-off strategy with the following phases:
* 1. A tight spin-lock loop (pending: using hardware PAUSE/YIELD instructions)
* 2. A loop where the current thread yields control after checking the lock.
* 3. Issuing a thread-sleep call before starting back in phase 1.
*
* This is meant to give a good balance of perofrmance and CPU consumption in
* practice.
*
* This class implements the `BasicLockable` specification:
* https://en.cppreference.com/w/cpp/named_req/BasicLockable
*/
class SpinLockMutex
{
public:
SpinLockMutex() noexcept {}
~SpinLockMutex() noexcept = default;
SpinLockMutex(const SpinLockMutex &) = delete;
SpinLockMutex &operator=(const SpinLockMutex &) = delete;
static inline void fast_yield() noexcept
{
// Issue a Pause/Yield instruction while spinning.
#if defined(_MSC_VER)
YieldProcessor();
#elif defined(__i386__) || defined(__x86_64__)
# if defined(__clang__) || defined(__INTEL_COMPILER)
_mm_pause();
# else
__builtin_ia32_pause();
# endif
#elif defined(__armel__) || defined(__ARMEL__)
asm volatile("nop" ::: "memory");
#elif defined(__arm__) || defined(__aarch64__) // arm big endian / arm64
__asm__ __volatile__("yield" ::: "memory");
#else
// TODO: Issue PAGE/YIELD on other architectures.
#endif
}
/**
* Attempts to lock the mutex. Return immediately with `true` (success) or `false` (failure).
*/
bool try_lock() noexcept
{
return !flag_.load(std::memory_order_relaxed) &&
!flag_.exchange(true, std::memory_order_acquire);
}
/**
* Blocks until a lock can be obtained for the current thread.
*
* This mutex will spin the current CPU waiting for the lock to be available. This can have
* decent performance in scenarios where there is low lock contention and lock-holders achieve
* their work quickly. It degrades in scenarios where locked tasks take a long time.
*/
void lock() noexcept
{
for (;;)
{
// Try once
if (!flag_.exchange(true, std::memory_order_acquire))
{
return;
}
// Spin-Fast (goal ~10ns)
for (std::size_t i = 0; i < SPINLOCK_FAST_ITERATIONS; ++i)
{
if (try_lock())
{
return;
}
fast_yield();
}
// Yield then try again (goal ~100ns)
std::this_thread::yield();
if (try_lock())
{
return;
}
// Sleep and then start the whole process again. (goal ~1000ns)
std::this_thread::sleep_for(std::chrono::milliseconds(SPINLOCK_SLEEP_MS));
}
return;
}
/** Releases the lock held by the execution agent. Throws no exceptions. */
void unlock() noexcept { flag_.store(false, std::memory_order_release); }
private:
std::atomic<bool> flag_{false};
};
} // namespace common
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,42 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace common
{
class StringUtil
{
public:
static nostd::string_view Trim(nostd::string_view str, size_t left, size_t right) noexcept
{
while (left <= right && isspace(str[left]))
{
left++;
}
while (left <= right && isspace(str[right]))
{
right--;
}
return str.substr(left, 1 + right - left);
}
static nostd::string_view Trim(nostd::string_view str) noexcept
{
if (str.empty())
{
return str;
}
return Trim(str, 0, str.size() - 1);
}
};
} // namespace common
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,206 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <chrono>
#include <cstdint>
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace common
{
/**
* @brief A timepoint relative to the system clock epoch.
*
* This is used for marking the beginning and end of an operation.
*/
class SystemTimestamp
{
public:
/**
* @brief Initializes a system timestamp pointing to the start of the epoch.
*/
SystemTimestamp() noexcept : nanos_since_epoch_{0} {}
/**
* @brief Initializes a system timestamp from a duration.
*
* @param time_since_epoch Time elapsed since the beginning of the epoch.
*/
template <class Rep, class Period>
explicit SystemTimestamp(const std::chrono::duration<Rep, Period> &time_since_epoch) noexcept
: nanos_since_epoch_{static_cast<int64_t>(
std::chrono::duration_cast<std::chrono::nanoseconds>(time_since_epoch).count())}
{}
/**
* @brief Initializes a system timestamp based on a point in time.
*
* @param time_point A point in time.
*/
/*implicit*/ SystemTimestamp(const std::chrono::system_clock::time_point &time_point) noexcept
: SystemTimestamp{time_point.time_since_epoch()}
{}
/**
* @brief Returns a time point for the time stamp.
*
* @return A time point corresponding to the time stamp.
*/
operator std::chrono::system_clock::time_point() const noexcept
{
return std::chrono::system_clock::time_point{
std::chrono::duration_cast<std::chrono::system_clock::duration>(
std::chrono::nanoseconds{nanos_since_epoch_})};
}
/**
* @brief Returns the nanoseconds since the beginning of the epoch.
*
* @return Elapsed nanoseconds since the beginning of the epoch for this timestamp.
*/
std::chrono::nanoseconds time_since_epoch() const noexcept
{
return std::chrono::nanoseconds{nanos_since_epoch_};
}
/**
* @brief Compare two steady time stamps.
*
* @return true if the two time stamps are equal.
*/
bool operator==(const SystemTimestamp &other) const noexcept
{
return nanos_since_epoch_ == other.nanos_since_epoch_;
}
/**
* @brief Compare two steady time stamps for inequality.
*
* @return true if the two time stamps are not equal.
*/
bool operator!=(const SystemTimestamp &other) const noexcept
{
return nanos_since_epoch_ != other.nanos_since_epoch_;
}
private:
int64_t nanos_since_epoch_;
};
/**
* @brief A timepoint relative to the monotonic clock epoch
*
* This is used for calculating the duration of an operation.
*/
class SteadyTimestamp
{
public:
/**
* @brief Initializes a monotonic timestamp pointing to the start of the epoch.
*/
SteadyTimestamp() noexcept : nanos_since_epoch_{0} {}
/**
* @brief Initializes a monotonic timestamp from a duration.
*
* @param time_since_epoch Time elapsed since the beginning of the epoch.
*/
template <class Rep, class Period>
explicit SteadyTimestamp(const std::chrono::duration<Rep, Period> &time_since_epoch) noexcept
: nanos_since_epoch_{static_cast<int64_t>(
std::chrono::duration_cast<std::chrono::nanoseconds>(time_since_epoch).count())}
{}
/**
* @brief Initializes a monotonic timestamp based on a point in time.
*
* @param time_point A point in time.
*/
/*implicit*/ SteadyTimestamp(const std::chrono::steady_clock::time_point &time_point) noexcept
: SteadyTimestamp{time_point.time_since_epoch()}
{}
/**
* @brief Returns a time point for the time stamp.
*
* @return A time point corresponding to the time stamp.
*/
operator std::chrono::steady_clock::time_point() const noexcept
{
return std::chrono::steady_clock::time_point{
std::chrono::duration_cast<std::chrono::steady_clock::duration>(
std::chrono::nanoseconds{nanos_since_epoch_})};
}
/**
* @brief Returns the nanoseconds since the beginning of the epoch.
*
* @return Elapsed nanoseconds since the beginning of the epoch for this timestamp.
*/
std::chrono::nanoseconds time_since_epoch() const noexcept
{
return std::chrono::nanoseconds{nanos_since_epoch_};
}
/**
* @brief Compare two steady time stamps.
*
* @return true if the two time stamps are equal.
*/
bool operator==(const SteadyTimestamp &other) const noexcept
{
return nanos_since_epoch_ == other.nanos_since_epoch_;
}
/**
* @brief Compare two steady time stamps for inequality.
*
* @return true if the two time stamps are not equal.
*/
bool operator!=(const SteadyTimestamp &other) const noexcept
{
return nanos_since_epoch_ != other.nanos_since_epoch_;
}
private:
int64_t nanos_since_epoch_;
};
class DurationUtil
{
public:
template <class Rep, class Period>
static std::chrono::duration<Rep, Period> AdjustWaitForTimeout(
std::chrono::duration<Rep, Period> timeout,
std::chrono::duration<Rep, Period> indefinite_value) noexcept
{
// Do not call now() when this duration is max value, now() may have a expensive cost.
if (timeout == (std::chrono::duration<Rep, Period>::max)())
{
return indefinite_value;
}
// std::future<T>::wait_for, std::this_thread::sleep_for, and std::condition_variable::wait_for
// may use steady_clock or system_clock.We need make sure now() + timeout do not overflow.
auto max_timeout = std::chrono::duration_cast<std::chrono::duration<Rep, Period>>(
(std::chrono::steady_clock::time_point::max)() - std::chrono::steady_clock::now());
if (timeout >= max_timeout)
{
return indefinite_value;
}
max_timeout = std::chrono::duration_cast<std::chrono::duration<Rep, Period>>(
(std::chrono::system_clock::time_point::max)() - std::chrono::system_clock::now());
if (timeout >= max_timeout)
{
return indefinite_value;
}
return timeout;
}
};
} // namespace common
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,19 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <type_traits> // IWYU pragma: keep
#if defined(OPENTELEMETRY_ABI_VERSION_NO) && OPENTELEMETRY_ABI_VERSION_NO >= 2
# error \
"opentelemetry/config.h is removed in ABI version 2 and later. Please use opentelemetry/version.h instead."
#else
# if defined(__clang__) || defined(__GNUC__)
# pragma GCC warning \
"opentelemetry/config.h is deprecated. Please use opentelemetry/version.h instead."
# elif defined(_MSC_VER)
# pragma message( \
"[WARNING]: opentelemetry/config.h is deprecated. Please use opentelemetry/version.h instead.")
# endif
#endif

View file

@ -0,0 +1,171 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <cstring>
#include <utility>
#include "opentelemetry/context/context_value.h"
#include "opentelemetry/nostd/shared_ptr.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/nostd/variant.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace context
{
// The context class provides a context identifier. Is built as a linked list
// of DataList nodes and each context holds a shared_ptr to a place within
// the list that determines which keys and values it has access to. All that
// come before and none that come after.
class Context
{
public:
Context() = default;
// Creates a context object from a map of keys and identifiers, this will
// hold a shared_ptr to the head of the DataList linked list
template <class T>
Context(const T &keys_and_values) noexcept
: head_{nostd::shared_ptr<DataList>{new DataList(keys_and_values)}}
{}
// Creates a context object from a key and value, this will
// hold a shared_ptr to the head of the DataList linked list
Context(nostd::string_view key, ContextValue value) noexcept
: head_{nostd::shared_ptr<DataList>{new DataList(key, value)}}
{}
// Accepts a new iterable and then returns a new context that
// contains the new key and value data. It attaches the
// exisiting list to the end of the new list.
template <class T>
Context SetValues(T &values) noexcept
{
Context context = Context(values);
nostd::shared_ptr<DataList> last = context.head_;
while (last->next_ != nullptr)
{
last = last->next_;
}
last->next_ = head_;
return context;
}
// Accepts a new iterable and then returns a new context that
// contains the new key and value data. It attaches the
// exisiting list to the end of the new list.
Context SetValue(nostd::string_view key, ContextValue value) noexcept
{
Context context = Context(key, value);
context.head_->next_ = head_;
return context;
}
// Returns the value associated with the passed in key.
context::ContextValue GetValue(const nostd::string_view key) const noexcept
{
for (DataList *data = head_.get(); data != nullptr; data = data->next_.get())
{
if (key.size() == data->key_length_)
{
if (std::memcmp(key.data(), data->key_, data->key_length_) == 0)
{
return data->value_;
}
}
}
return ContextValue{};
}
// Checks for key and returns true if found
bool HasKey(const nostd::string_view key) const noexcept
{
return !nostd::holds_alternative<nostd::monostate>(GetValue(key));
}
bool operator==(const Context &other) const noexcept { return (head_ == other.head_); }
private:
// A linked list to contain the keys and values of this context node
struct DataList
{
char *key_ = nullptr;
nostd::shared_ptr<DataList> next_{nullptr};
size_t key_length_ = 0UL;
ContextValue value_;
DataList() = default;
// Builds a data list off of a key and value iterable and returns the head
template <class T>
DataList(const T &keys_and_vals)
{
bool first = true;
auto *node = this;
for (auto &iter : keys_and_vals)
{
if (first)
{
*node = DataList(iter.first, iter.second);
first = false;
}
else
{
node->next_ = nostd::shared_ptr<DataList>(new DataList(iter.first, iter.second));
node = node->next_.get();
}
}
}
// Builds a data list with just a key and value, so it will just be the head
// and returns that head.
DataList(nostd::string_view key, const ContextValue &value)
{
key_ = new char[key.size()];
key_length_ = key.size();
std::memcpy(key_, key.data(), key.size() * sizeof(char));
next_ = nostd::shared_ptr<DataList>{nullptr};
value_ = value;
}
DataList(const DataList &other)
: key_(new char[other.key_length_]),
next_(other.next_),
key_length_(other.key_length_),
value_(other.value_)
{
std::memcpy(key_, other.key_, other.key_length_ * sizeof(char));
}
DataList &operator=(DataList &&other) noexcept
{
key_length_ = other.key_length_;
value_ = std::move(other.value_);
next_ = std::move(other.next_);
key_ = other.key_;
other.key_ = nullptr;
return *this;
}
~DataList()
{
if (key_ != nullptr)
{
delete[] key_;
}
}
};
// Head of the list which holds the keys and values of this context
nostd::shared_ptr<DataList> head_;
};
} // namespace context
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,35 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <cstdint>
#include "opentelemetry/nostd/shared_ptr.h"
#include "opentelemetry/nostd/variant.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace baggage
{
class Baggage;
} // namespace baggage
namespace trace
{
class Span;
class SpanContext;
} // namespace trace
namespace context
{
using ContextValue = nostd::variant<nostd::monostate,
bool,
int64_t,
uint64_t,
double,
nostd::shared_ptr<trace::Span>,
nostd::shared_ptr<trace::SpanContext>,
nostd::shared_ptr<baggage::Baggage>>;
} // namespace context
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,93 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <memory>
#include <vector>
#include "opentelemetry/context/propagation/text_map_propagator.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace context
{
namespace propagation
{
class CompositePropagator : public TextMapPropagator
{
public:
CompositePropagator(std::vector<std::unique_ptr<TextMapPropagator>> propagators)
: propagators_(std::move(propagators))
{}
/**
* Run each of the configured propagators with the given context and carrier.
* Propagators are run in the order they are configured, so if multiple
* propagators write the same carrier key, the propagator later in the list
* will "win".
*
* @param carrier Carrier into which context will be injected
* @param context Context to inject
*
*/
void Inject(TextMapCarrier &carrier, const context::Context &context) noexcept override
{
for (auto &p : propagators_)
{
p->Inject(carrier, context);
}
}
/**
* Run each of the configured propagators with the given context and carrier.
* Propagators are run in the order they are configured, so if multiple
* propagators write the same context key, the propagator later in the list
* will "win".
*
* @param carrier Carrier from which to extract context
* @param context Context to add values to
*/
context::Context Extract(const TextMapCarrier &carrier,
context::Context &context) noexcept override
{
auto first = true;
context::Context tmp_context;
for (auto &p : propagators_)
{
if (first)
{
tmp_context = p->Extract(carrier, context);
first = false;
}
else
{
tmp_context = p->Extract(carrier, tmp_context);
}
}
return propagators_.size() ? tmp_context : context;
}
/**
* Invoke callback with fields set to carrier by `inject` method for all the
* configured propagators
* Returns true if all invocation return true
*/
bool Fields(nostd::function_ref<bool(nostd::string_view)> callback) const noexcept override
{
bool status = true;
for (auto &p : propagators_)
{
status = status && p->Fields(callback);
}
return status;
}
private:
std::vector<std::unique_ptr<TextMapPropagator>> propagators_;
};
} // namespace propagation
} // namespace context
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,57 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <mutex>
#include "opentelemetry/context/propagation/noop_propagator.h"
#include "opentelemetry/common/macros.h"
#include "opentelemetry/common/spin_lock_mutex.h"
#include "opentelemetry/nostd/shared_ptr.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace context
{
namespace propagation
{
class TextMapPropagator;
/* Stores the singleton TextMapPropagator */
class OPENTELEMETRY_EXPORT GlobalTextMapPropagator
{
public:
static nostd::shared_ptr<TextMapPropagator> GetGlobalPropagator() noexcept
{
std::lock_guard<common::SpinLockMutex> guard(GetLock());
return nostd::shared_ptr<TextMapPropagator>(GetPropagator());
}
static void SetGlobalPropagator(const nostd::shared_ptr<TextMapPropagator> &prop) noexcept
{
std::lock_guard<common::SpinLockMutex> guard(GetLock());
GetPropagator() = prop;
}
private:
OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr<TextMapPropagator> &GetPropagator() noexcept
{
static nostd::shared_ptr<TextMapPropagator> propagator(new NoOpPropagator());
return propagator;
}
OPENTELEMETRY_API_SINGLETON static common::SpinLockMutex &GetLock() noexcept
{
static common::SpinLockMutex lock;
return lock;
}
};
} // namespace propagation
} // namespace context
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,40 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "opentelemetry/context/propagation/text_map_propagator.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace context
{
namespace propagation
{
/**
* No-op implementation TextMapPropagator
*/
class NoOpPropagator : public TextMapPropagator
{
public:
/** Noop extract function does nothing and returns the input context */
context::Context Extract(const TextMapCarrier & /*carrier*/,
context::Context &context) noexcept override
{
return context;
}
/** Noop inject function does nothing */
void Inject(TextMapCarrier & /*carrier*/,
const context::Context & /* context */) noexcept override
{}
bool Fields(nostd::function_ref<bool(nostd::string_view)> /* callback */) const noexcept override
{
return true;
}
};
} // namespace propagation
} // namespace context
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,59 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "opentelemetry/context/context.h"
#include "opentelemetry/nostd/function_ref.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace context
{
namespace propagation
{
// TextMapCarrier is the storage medium used by TextMapPropagator.
class TextMapCarrier
{
public:
// returns the value associated with the passed key.
virtual nostd::string_view Get(nostd::string_view key) const noexcept = 0;
// stores the key-value pair.
virtual void Set(nostd::string_view key, nostd::string_view value) noexcept = 0;
/* list of all the keys in the carrier.
By default, it returns true without invoking callback */
virtual bool Keys(nostd::function_ref<bool(nostd::string_view)> /* callback */) const noexcept
{
return true;
}
virtual ~TextMapCarrier() = default;
};
// The TextMapPropagator class provides an interface that enables extracting and injecting
// context into carriers that travel in-band across process boundaries. HTTP frameworks and clients
// can integrate with TextMapPropagator by providing the object containing the
// headers, and a getter and setter function for the extraction and
// injection of values, respectively.
class TextMapPropagator
{
public:
// Returns the context that is stored in the carrier with the TextMapCarrier as extractor.
virtual context::Context Extract(const TextMapCarrier &carrier,
context::Context &context) noexcept = 0;
// Sets the context for carrier with self defined rules.
virtual void Inject(TextMapCarrier &carrier, const context::Context &context) noexcept = 0;
// Gets the fields set in the carrier by the `inject` method
virtual bool Fields(nostd::function_ref<bool(nostd::string_view)> callback) const noexcept = 0;
virtual ~TextMapPropagator() = default;
};
} // namespace propagation
} // namespace context
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,340 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <stddef.h>
#include <algorithm>
#include "opentelemetry/common/macros.h"
#include "opentelemetry/context/context.h"
#include "opentelemetry/context/context_value.h"
#include "opentelemetry/nostd/shared_ptr.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/nostd/unique_ptr.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace context
{
// The Token object provides is returned when attaching objects to the
// RuntimeContext object and is associated with a context object, and
// can be provided to the RuntimeContext Detach method to remove the
// associated context from the RuntimeContext.
class Token
{
public:
bool operator==(const Context &other) const noexcept { return context_ == other; }
~Token() noexcept;
private:
friend class RuntimeContextStorage;
// A constructor that sets the token's Context object to the
// one that was passed in.
Token(const Context &context) : context_(context) {}
const Context context_;
};
/**
* RuntimeContextStorage is used by RuntimeContext to store Context frames.
*
* Custom context management strategies can be implemented by deriving from
* this class and passing an initialized RuntimeContextStorage object to
* RuntimeContext::SetRuntimeContextStorage.
*/
class OPENTELEMETRY_EXPORT RuntimeContextStorage
{
public:
/**
* Return the current context.
* @return the current context
*/
virtual Context GetCurrent() noexcept = 0;
/**
* Set the current context.
* @param the new current context
* @return a token for the new current context. This never returns a nullptr.
*/
virtual nostd::unique_ptr<Token> Attach(const Context &context) noexcept = 0;
/**
* Detach the context related to the given token.
* @param token a token related to a context
* @return true if the context could be detached
*/
virtual bool Detach(Token &token) noexcept = 0;
virtual ~RuntimeContextStorage() {}
protected:
nostd::unique_ptr<Token> CreateToken(const Context &context) noexcept
{
return nostd::unique_ptr<Token>(new Token(context));
}
};
/**
* Construct and return the default RuntimeContextStorage
* @return a ThreadLocalContextStorage
*/
static RuntimeContextStorage *GetDefaultStorage() noexcept;
// Provides a wrapper for propagating the context object globally.
//
// By default, a thread-local runtime context storage is used.
class OPENTELEMETRY_EXPORT RuntimeContext
{
public:
// Return the current context.
static Context GetCurrent() noexcept { return GetRuntimeContextStorage()->GetCurrent(); }
// Sets the current 'Context' object. Returns a token
// that can be used to reset to the previous Context.
static nostd::unique_ptr<Token> Attach(const Context &context) noexcept
{
return GetRuntimeContextStorage()->Attach(context);
}
// Resets the context to a previous value stored in the
// passed in token. Returns true if successful, false otherwise
static bool Detach(Token &token) noexcept { return GetRuntimeContextStorage()->Detach(token); }
// Sets the Key and Value into the passed in context or if a context is not
// passed in, the RuntimeContext.
// Should be used to SetValues to the current RuntimeContext, is essentially
// equivalent to RuntimeContext::GetCurrent().SetValue(key,value). Keep in
// mind that the current RuntimeContext will not be changed, and the new
// context will be returned.
static Context SetValue(nostd::string_view key,
const ContextValue &value,
Context *context = nullptr) noexcept
{
Context temp_context;
if (context == nullptr)
{
temp_context = GetCurrent();
}
else
{
temp_context = *context;
}
return temp_context.SetValue(key, value);
}
// Returns the value associated with the passed in key and either the
// passed in context* or the runtime context if a context is not passed in.
// Should be used to get values from the current RuntimeContext, is
// essentially equivalent to RuntimeContext::GetCurrent().GetValue(key).
static ContextValue GetValue(nostd::string_view key, Context *context = nullptr) noexcept
{
Context temp_context;
if (context == nullptr)
{
temp_context = GetCurrent();
}
else
{
temp_context = *context;
}
return temp_context.GetValue(key);
}
/**
* Provide a custom runtime context storage.
*
* This provides a possibility to override the default thread-local runtime
* context storage. This has to be set before any spans are created by the
* application, otherwise the behavior is undefined.
*
* @param storage a custom runtime context storage
*/
static void SetRuntimeContextStorage(
const nostd::shared_ptr<RuntimeContextStorage> &storage) noexcept
{
GetStorage() = storage;
}
/**
* Provide a pointer to const runtime context storage.
*
* The returned pointer can only be used for extending the lifetime of the runtime context
* storage.
*
*/
static nostd::shared_ptr<const RuntimeContextStorage> GetConstRuntimeContextStorage() noexcept
{
return GetRuntimeContextStorage();
}
private:
static nostd::shared_ptr<RuntimeContextStorage> GetRuntimeContextStorage() noexcept
{
return GetStorage();
}
OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr<RuntimeContextStorage> &GetStorage() noexcept
{
static nostd::shared_ptr<RuntimeContextStorage> context(GetDefaultStorage());
return context;
}
};
inline Token::~Token() noexcept
{
context::RuntimeContext::Detach(*this);
}
// The ThreadLocalContextStorage class is a derived class from
// RuntimeContextStorage and provides a wrapper for propagating context through
// cpp thread locally. This file must be included to use the RuntimeContext
// class if another implementation has not been registered.
class ThreadLocalContextStorage : public RuntimeContextStorage
{
public:
ThreadLocalContextStorage() noexcept = default;
// Return the current context.
Context GetCurrent() noexcept override { return GetStack().Top(); }
// Resets the context to the value previous to the passed in token. This will
// also detach all child contexts of the passed in token.
// Returns true if successful, false otherwise.
bool Detach(Token &token) noexcept override
{
// In most cases, the context to be detached is on the top of the stack.
if (token == GetStack().Top())
{
GetStack().Pop();
return true;
}
if (!GetStack().Contains(token))
{
return false;
}
while (!(token == GetStack().Top()))
{
GetStack().Pop();
}
GetStack().Pop();
return true;
}
// Sets the current 'Context' object. Returns a token
// that can be used to reset to the previous Context.
nostd::unique_ptr<Token> Attach(const Context &context) noexcept override
{
GetStack().Push(context);
return CreateToken(context);
}
private:
// A nested class to store the attached contexts in a stack.
class Stack
{
friend class ThreadLocalContextStorage;
Stack() noexcept : size_(0), capacity_(0), base_(nullptr) {}
// Pops the top Context off the stack.
void Pop() noexcept
{
if (size_ == 0)
{
return;
}
// Store empty Context before decrementing `size`, to ensure
// the shared_ptr object (if stored in prev context object ) are released.
// The stack is not resized, and the unused memory would be reutilised
// for subsequent context storage.
base_[size_ - 1] = Context();
size_ -= 1;
}
bool Contains(const Token &token) const noexcept
{
for (size_t pos = size_; pos > 0; --pos)
{
if (token == base_[pos - 1])
{
return true;
}
}
return false;
}
// Returns the Context at the top of the stack.
Context Top() const noexcept
{
if (size_ == 0)
{
return Context();
}
return base_[size_ - 1];
}
// Pushes the passed in context pointer to the top of the stack
// and resizes if necessary.
void Push(const Context &context) noexcept
{
size_++;
if (size_ > capacity_)
{
Resize(size_ * 2);
}
base_[size_ - 1] = context;
}
// Reallocates the storage array to the pass in new capacity size.
void Resize(size_t new_capacity) noexcept
{
size_t old_size = size_ - 1;
if (new_capacity == 0)
{
new_capacity = 2;
}
Context *temp = new Context[new_capacity];
if (base_ != nullptr)
{
// vs2015 does not like this construct considering it unsafe:
// - std::copy(base_, base_ + old_size, temp);
// Ref.
// https://stackoverflow.com/questions/12270224/xutility2227-warning-c4996-std-copy-impl
for (size_t i = 0; i < (std::min)(old_size, new_capacity); i++)
{
temp[i] = base_[i];
}
delete[] base_;
}
base_ = temp;
capacity_ = new_capacity;
}
~Stack() noexcept { delete[] base_; }
size_t size_;
size_t capacity_;
Context *base_;
};
OPENTELEMETRY_API_SINGLETON Stack &GetStack()
{
static thread_local Stack stack_ = Stack();
return stack_;
}
};
static RuntimeContextStorage *GetDefaultStorage() noexcept
{
return new ThreadLocalContextStorage();
}
} // namespace context
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,25 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
// NOTE - code within detail namespace implements internal details, and not part
// of the public interface.
#pragma once
#define OPENTELEMETRY_STRINGIFY(S) OPENTELEMETRY_STRINGIFY_(S)
#define OPENTELEMETRY_STRINGIFY_(S) #S
#define OPENTELEMETRY_CONCAT(A, B) OPENTELEMETRY_CONCAT_(A, B)
#define OPENTELEMETRY_CONCAT_(A, B) A##B
// Import the C++20 feature-test macros
#ifdef __has_include
# if __has_include(<version>)
# include <version>
# endif
#elif defined(_MSC_VER) && ((defined(__cplusplus) && __cplusplus >= 202002L) || \
(defined(_MSVC_LANG) && _MSVC_LANG >= 202002L))
# if _MSC_VER >= 1922
# include <version>
# endif
#endif

View file

@ -0,0 +1,37 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <algorithm>
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/nostd/unique_ptr.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace logs
{
/**
* EventId class which acts the Id of the event with an optional name.
*/
class EventId
{
public:
EventId(int64_t id, nostd::string_view name) noexcept
: id_{id}, name_{nostd::unique_ptr<char[]>{new char[name.length() + 1]}}
{
std::copy(name.begin(), name.end(), name_.get());
name_.get()[name.length()] = 0;
}
EventId(int64_t id) noexcept : id_{id}, name_{nullptr} {}
public:
int64_t id_;
nostd::unique_ptr<char[]> name_;
};
} // namespace logs
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,82 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "opentelemetry/logs/log_record.h"
#include "opentelemetry/logs/logger.h"
#include "opentelemetry/logs/logger_type_traits.h"
#include "opentelemetry/nostd/shared_ptr.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/nostd/unique_ptr.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace logs
{
#if OPENTELEMETRY_ABI_VERSION_NO < 2
/**
* Handles event log record creation.
**/
class OPENTELEMETRY_DEPRECATED EventLogger
{
public:
virtual ~EventLogger() = default;
/* Returns the name of the logger */
virtual const nostd::string_view GetName() noexcept = 0;
/* Returns the delegate logger of this event logger */
virtual nostd::shared_ptr<Logger> GetDelegateLogger() noexcept = 0;
/**
* Emit a event Log Record object
*
* @param event_name Event name
* @param log_record Log record
*/
virtual void EmitEvent(nostd::string_view event_name,
nostd::unique_ptr<LogRecord> &&log_record) noexcept = 0;
/**
* Emit a event Log Record object with arguments
*
* @param event_name Event name
* @tparam args Arguments which can be used to set data of log record by type.
* Severity -> severity, severity_text
* string_view -> body
* AttributeValue -> body
* SpanContext -> span_id,tace_id and trace_flags
* SpanId -> span_id
* TraceId -> tace_id
* TraceFlags -> trace_flags
* SystemTimestamp -> timestamp
* system_clock::time_point -> timestamp
* KeyValueIterable -> attributes
* Key value iterable container -> attributes
* span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
*/
template <class... ArgumentType>
void EmitEvent(nostd::string_view event_name, ArgumentType &&...args)
{
nostd::shared_ptr<Logger> delegate_logger = GetDelegateLogger();
if (!delegate_logger)
{
return;
}
nostd::unique_ptr<LogRecord> log_record = delegate_logger->CreateLogRecord();
IgnoreTraitResult(detail::LogRecordSetterTrait<typename std::decay<ArgumentType>::type>::Set(
log_record.get(), std::forward<ArgumentType>(args))...);
EmitEvent(event_name, std::move(log_record));
}
private:
template <class... ValueType>
void IgnoreTraitResult(ValueType &&...)
{}
};
#endif
} // namespace logs
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,37 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "opentelemetry/nostd/shared_ptr.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace logs
{
class EventLogger;
class Logger;
#if OPENTELEMETRY_ABI_VERSION_NO < 2
/**
* Creates new EventLogger instances.
*/
class OPENTELEMETRY_DEPRECATED EventLoggerProvider
{
public:
virtual ~EventLoggerProvider() = default;
/**
* Creates a named EventLogger instance.
*
*/
virtual nostd::shared_ptr<EventLogger> CreateEventLogger(
nostd::shared_ptr<Logger> delegate_logger,
nostd::string_view event_domain) noexcept = 0;
};
#endif
} // namespace logs
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,92 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "opentelemetry/common/attribute_value.h"
#include "opentelemetry/common/timestamp.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace trace
{
class SpanId;
class TraceId;
class TraceFlags;
} // namespace trace
namespace logs
{
enum class Severity : uint8_t;
/**
* Maintains a representation of a log in a format that can be processed by a recorder.
*
* This class is thread-compatible.
*/
class LogRecord
{
public:
virtual ~LogRecord() = default;
/**
* Set the timestamp for this log.
* @param timestamp the timestamp to set
*/
virtual void SetTimestamp(common::SystemTimestamp timestamp) noexcept = 0;
/**
* Set the observed timestamp for this log.
* @param timestamp the timestamp to set
*/
virtual void SetObservedTimestamp(common::SystemTimestamp timestamp) noexcept = 0;
/**
* Set the severity for this log.
* @param severity the severity of the event
*/
virtual void SetSeverity(logs::Severity severity) noexcept = 0;
/**
* Set body field for this log.
* @param message the body to set
*/
virtual void SetBody(const common::AttributeValue &message) noexcept = 0;
/**
* Set an attribute of a log.
* @param key the name of the attribute
* @param value the attribute value
*/
virtual void SetAttribute(nostd::string_view key,
const common::AttributeValue &value) noexcept = 0;
/**
* Set the Event Id.
* @param id The event id to set
* @param name Optional event name to set
*/
// TODO: mark this as pure virtual once all exporters have been updated
virtual void SetEventId(int64_t id, nostd::string_view name = {}) noexcept = 0;
/**
* Set the trace id for this log.
* @param trace_id the trace id to set
*/
virtual void SetTraceId(const trace::TraceId &trace_id) noexcept = 0;
/**
* Set the span id for this log.
* @param span_id the span id to set
*/
virtual void SetSpanId(const trace::SpanId &span_id) noexcept = 0;
/**
* Inject trace_flags for this log.
* @param trace_flags the trace flags to set
*/
virtual void SetTraceFlags(const trace::TraceFlags &trace_flags) noexcept = 0;
};
} // namespace logs
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,492 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "opentelemetry/logs/logger_type_traits.h"
#include "opentelemetry/logs/severity.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/nostd/unique_ptr.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace common
{
class KeyValueIterable;
} // namespace common
namespace logs
{
class EventId;
class LogRecord;
/**
* Handles log record creation.
**/
class Logger
{
public:
virtual ~Logger() = default;
/* Returns the name of the logger */
virtual const nostd::string_view GetName() noexcept = 0;
/**
* Create a Log Record object
*
* @return nostd::unique_ptr<LogRecord>
*/
virtual nostd::unique_ptr<LogRecord> CreateLogRecord() noexcept = 0;
/**
* Emit a Log Record object
*
* @param log_record Log record
*/
virtual void EmitLogRecord(nostd::unique_ptr<LogRecord> &&log_record) noexcept = 0;
/**
* Emit a Log Record object with arguments
*
* @param log_record Log record
* @param args Arguments which can be used to set data of log record by type.
* Severity -> severity, severity_text
* string_view -> body
* AttributeValue -> body
* SpanContext -> span_id,trace_id and trace_flags
* SpanId -> span_id
* TraceId -> trace_id
* TraceFlags -> trace_flags
* SystemTimestamp -> timestamp
* system_clock::time_point -> timestamp
* KeyValueIterable -> attributes
* Key value iterable container -> attributes
* span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
*/
template <class... ArgumentType>
void EmitLogRecord(nostd::unique_ptr<LogRecord> &&log_record, ArgumentType &&...args)
{
if (!log_record)
{
return;
}
//
// Keep the parameter pack unpacking order from left to right because left
// ones are usually more important like severity and event_id than the
// attributes. The left to right unpack order could pass the more important
// data to processors to avoid caching and memory allocating.
//
#if __cplusplus <= 201402L
// C++14 does not support fold expressions for parameter pack expansion.
int dummy[] = {(detail::LogRecordSetterTrait<typename std::decay<ArgumentType>::type>::Set(
log_record.get(), std::forward<ArgumentType>(args)),
0)...};
IgnoreTraitResult(dummy);
#else
IgnoreTraitResult((detail::LogRecordSetterTrait<typename std::decay<ArgumentType>::type>::Set(
log_record.get(), std::forward<ArgumentType>(args)),
...));
#endif
EmitLogRecord(std::move(log_record));
}
/**
* Emit a Log Record object with arguments
*
* @param args Arguments which can be used to set data of log record by type.
* Severity -> severity, severity_text
* string_view -> body
* AttributeValue -> body
* SpanContext -> span_id,trace_id and trace_flags
* SpanId -> span_id
* TraceId -> trace_id
* TraceFlags -> trace_flags
* SystemTimestamp -> timestamp
* system_clock::time_point -> timestamp
* KeyValueIterable -> attributes
* Key value iterable container -> attributes
* span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
*/
template <class... ArgumentType>
void EmitLogRecord(ArgumentType &&...args)
{
nostd::unique_ptr<LogRecord> log_record = CreateLogRecord();
EmitLogRecord(std::move(log_record), std::forward<ArgumentType>(args)...);
}
/**
* Writes a log with a severity of trace.
* @param args Arguments which can be used to set data of log record by type.
* string_view -> body
* AttributeValue -> body
* SpanContext -> span_id,trace_id and trace_flags
* SpanId -> span_id
* TraceId -> trace_id
* TraceFlags -> trace_flags
* SystemTimestamp -> timestamp
* system_clock::time_point -> timestamp
* KeyValueIterable -> attributes
* Key value iterable container -> attributes
* span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
*/
template <class... ArgumentType>
void Trace(ArgumentType &&...args) noexcept
{
static_assert(
!detail::LogRecordHasType<Severity, typename std::decay<ArgumentType>::type...>::value,
"Severity is already set.");
this->EmitLogRecord(Severity::kTrace, std::forward<ArgumentType>(args)...);
}
/**
* Writes a log with a severity of debug.
* @param args Arguments which can be used to set data of log record by type.
* string_view -> body
* AttributeValue -> body
* SpanContext -> span_id,trace_id and trace_flags
* SpanId -> span_id
* TraceId -> trace_id
* TraceFlags -> trace_flags
* SystemTimestamp -> timestamp
* system_clock::time_point -> timestamp
* KeyValueIterable -> attributes
* Key value iterable container -> attributes
* span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
*/
template <class... ArgumentType>
void Debug(ArgumentType &&...args) noexcept
{
static_assert(
!detail::LogRecordHasType<Severity, typename std::decay<ArgumentType>::type...>::value,
"Severity is already set.");
this->EmitLogRecord(Severity::kDebug, std::forward<ArgumentType>(args)...);
}
/**
* Writes a log with a severity of info.
* @param args Arguments which can be used to set data of log record by type.
* string_view -> body
* AttributeValue -> body
* SpanContext -> span_id,trace_id and trace_flags
* SpanId -> span_id
* TraceId -> trace_id
* TraceFlags -> trace_flags
* SystemTimestamp -> timestamp
* system_clock::time_point -> timestamp
* KeyValueIterable -> attributes
* Key value iterable container -> attributes
* span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
*/
template <class... ArgumentType>
void Info(ArgumentType &&...args) noexcept
{
static_assert(
!detail::LogRecordHasType<Severity, typename std::decay<ArgumentType>::type...>::value,
"Severity is already set.");
this->EmitLogRecord(Severity::kInfo, std::forward<ArgumentType>(args)...);
}
/**
* Writes a log with a severity of warn.
* @param args Arguments which can be used to set data of log record by type.
* string_view -> body
* AttributeValue -> body
* SpanContext -> span_id,trace_id and trace_flags
* SpanId -> span_id
* TraceId -> trace_id
* TraceFlags -> trace_flags
* SystemTimestamp -> timestamp
* system_clock::time_point -> timestamp
* KeyValueIterable -> attributes
* Key value iterable container -> attributes
* span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
*/
template <class... ArgumentType>
void Warn(ArgumentType &&...args) noexcept
{
static_assert(
!detail::LogRecordHasType<Severity, typename std::decay<ArgumentType>::type...>::value,
"Severity is already set.");
this->EmitLogRecord(Severity::kWarn, std::forward<ArgumentType>(args)...);
}
/**
* Writes a log with a severity of error.
* @param args Arguments which can be used to set data of log record by type.
* string_view -> body
* AttributeValue -> body
* SpanContext -> span_id,trace_id and trace_flags
* SpanId -> span_id
* TraceId -> trace_id
* TraceFlags -> trace_flags
* SystemTimestamp -> timestamp
* system_clock::time_point -> timestamp
* KeyValueIterable -> attributes
* Key value iterable container -> attributes
* span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
*/
template <class... ArgumentType>
void Error(ArgumentType &&...args) noexcept
{
static_assert(
!detail::LogRecordHasType<Severity, typename std::decay<ArgumentType>::type...>::value,
"Severity is already set.");
this->EmitLogRecord(Severity::kError, std::forward<ArgumentType>(args)...);
}
/**
* Writes a log with a severity of fatal.
* @param args Arguments which can be used to set data of log record by type.
* string_view -> body
* AttributeValue -> body
* SpanContext -> span_id,trace_id and trace_flags
* SpanId -> span_id
* TraceId -> trace_id
* TraceFlags -> trace_flags
* SystemTimestamp -> timestamp
* system_clock::time_point -> timestamp
* KeyValueIterable -> attributes
* Key value iterable container -> attributes
* span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
*/
template <class... ArgumentType>
void Fatal(ArgumentType &&...args) noexcept
{
static_assert(
!detail::LogRecordHasType<Severity, typename std::decay<ArgumentType>::type...>::value,
"Severity is already set.");
this->EmitLogRecord(Severity::kFatal, std::forward<ArgumentType>(args)...);
}
//
// OpenTelemetry C++ user-facing Logs API
//
inline bool Enabled(Severity severity, const EventId &event_id) const noexcept
{
if OPENTELEMETRY_LIKELY_CONDITION (!Enabled(severity))
{
return false;
}
return EnabledImplementation(severity, event_id);
}
inline bool Enabled(Severity severity, int64_t event_id) const noexcept
{
if OPENTELEMETRY_LIKELY_CONDITION (!Enabled(severity))
{
return false;
}
return EnabledImplementation(severity, event_id);
}
inline bool Enabled(Severity severity) const noexcept
{
return static_cast<uint8_t>(severity) >= OPENTELEMETRY_ATOMIC_READ_8(&minimum_severity_);
}
/**
* Log an event
*
* @severity severity of the log
* @event_id event identifier of the log
* @format an utf-8 string following https://messagetemplates.org/
* @attributes key value pairs of the log
*/
virtual void Log(Severity severity,
const EventId &event_id,
nostd::string_view format,
const common::KeyValueIterable &attributes) noexcept
{
this->EmitLogRecord(severity, event_id, format, attributes);
}
virtual void Log(Severity severity,
int64_t event_id,
nostd::string_view format,
const common::KeyValueIterable &attributes) noexcept
{
this->EmitLogRecord(severity, EventId{event_id}, format, attributes);
}
virtual void Log(Severity severity,
nostd::string_view format,
const common::KeyValueIterable &attributes) noexcept
{
this->EmitLogRecord(severity, format, attributes);
}
virtual void Log(Severity severity, nostd::string_view message) noexcept
{
this->EmitLogRecord(severity, message);
}
// Convenient wrappers based on virtual methods Log().
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#field-severitynumber
inline void Trace(const EventId &event_id,
nostd::string_view format,
const common::KeyValueIterable &attributes) noexcept
{
this->Log(Severity::kTrace, event_id, format, attributes);
}
inline void Trace(int64_t event_id,
nostd::string_view format,
const common::KeyValueIterable &attributes) noexcept
{
this->Log(Severity::kTrace, EventId{event_id}, format, attributes);
}
inline void Trace(nostd::string_view format, const common::KeyValueIterable &attributes) noexcept
{
this->Log(Severity::kTrace, format, attributes);
}
inline void Trace(nostd::string_view message) noexcept { this->Log(Severity::kTrace, message); }
inline void Debug(const EventId &event_id,
nostd::string_view format,
const common::KeyValueIterable &attributes) noexcept
{
this->Log(Severity::kDebug, event_id, format, attributes);
}
inline void Debug(int64_t event_id,
nostd::string_view format,
const common::KeyValueIterable &attributes) noexcept
{
this->Log(Severity::kDebug, EventId{event_id}, format, attributes);
}
inline void Debug(nostd::string_view format, const common::KeyValueIterable &attributes) noexcept
{
this->Log(Severity::kDebug, format, attributes);
}
inline void Debug(nostd::string_view message) noexcept { this->Log(Severity::kDebug, message); }
inline void Info(const EventId &event_id,
nostd::string_view format,
const common::KeyValueIterable &attributes) noexcept
{
this->Log(Severity::kInfo, event_id, format, attributes);
}
inline void Info(int64_t event_id,
nostd::string_view format,
const common::KeyValueIterable &attributes) noexcept
{
this->Log(Severity::kInfo, EventId{event_id}, format, attributes);
}
inline void Info(nostd::string_view format, const common::KeyValueIterable &attributes) noexcept
{
this->Log(Severity::kInfo, format, attributes);
}
inline void Info(nostd::string_view message) noexcept { this->Log(Severity::kInfo, message); }
inline void Warn(const EventId &event_id,
nostd::string_view format,
const common::KeyValueIterable &attributes) noexcept
{
this->Log(Severity::kWarn, event_id, format, attributes);
}
inline void Warn(int64_t event_id,
nostd::string_view format,
const common::KeyValueIterable &attributes) noexcept
{
this->Log(Severity::kWarn, EventId{event_id}, format, attributes);
}
inline void Warn(nostd::string_view format, const common::KeyValueIterable &attributes) noexcept
{
this->Log(Severity::kWarn, format, attributes);
}
inline void Warn(nostd::string_view message) noexcept { this->Log(Severity::kWarn, message); }
inline void Error(const EventId &event_id,
nostd::string_view format,
const common::KeyValueIterable &attributes) noexcept
{
this->Log(Severity::kError, event_id, format, attributes);
}
inline void Error(int64_t event_id,
nostd::string_view format,
const common::KeyValueIterable &attributes) noexcept
{
this->Log(Severity::kError, EventId{event_id}, format, attributes);
}
inline void Error(nostd::string_view format, const common::KeyValueIterable &attributes) noexcept
{
this->Log(Severity::kError, format, attributes);
}
inline void Error(nostd::string_view message) noexcept { this->Log(Severity::kError, message); }
inline void Fatal(const EventId &event_id,
nostd::string_view format,
const common::KeyValueIterable &attributes) noexcept
{
this->Log(Severity::kFatal, event_id, format, attributes);
}
inline void Fatal(int64_t event_id,
nostd::string_view format,
const common::KeyValueIterable &attributes) noexcept
{
this->Log(Severity::kFatal, EventId{event_id}, format, attributes);
}
inline void Fatal(nostd::string_view format, const common::KeyValueIterable &attributes) noexcept
{
this->Log(Severity::kFatal, format, attributes);
}
inline void Fatal(nostd::string_view message) noexcept { this->Log(Severity::kFatal, message); }
//
// End of OpenTelemetry C++ user-facing Log API.
//
protected:
// TODO: discuss with community about naming for internal methods.
virtual bool EnabledImplementation(Severity /*severity*/,
const EventId & /*event_id*/) const noexcept
{
return false;
}
virtual bool EnabledImplementation(Severity /*severity*/, int64_t /*event_id*/) const noexcept
{
return false;
}
void SetMinimumSeverity(uint8_t severity_or_max) noexcept
{
OPENTELEMETRY_ATOMIC_WRITE_8(&minimum_severity_, severity_or_max);
}
private:
template <class... ValueType>
void IgnoreTraitResult(ValueType &&...)
{}
//
// minimum_severity_ can be updated concurrently by multiple threads/cores, so race condition on
// read/write should be handled. And std::atomic can not be used here because it is not ABI
// compatible for OpenTelemetry C++ API.
//
mutable uint8_t minimum_severity_{kMaxSeverity};
};
} // namespace logs
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,71 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "opentelemetry/common/key_value_iterable.h"
#include "opentelemetry/common/key_value_iterable_view.h"
#include "opentelemetry/nostd/shared_ptr.h"
#include "opentelemetry/nostd/span.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/nostd/type_traits.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace logs
{
class Logger;
/**
* Creates new Logger instances.
*/
class OPENTELEMETRY_EXPORT LoggerProvider
{
public:
virtual ~LoggerProvider() = default;
/**
* Gets or creates a named Logger instance.
*
* Optionally a version can be passed to create a named and versioned Logger
* instance.
*
* Optionally a configuration file name can be passed to create a configuration for
* the Logger instance.
*
*/
virtual nostd::shared_ptr<Logger> GetLogger(
nostd::string_view logger_name,
nostd::string_view library_name = "",
nostd::string_view library_version = "",
nostd::string_view schema_url = "",
const common::KeyValueIterable &attributes = common::NoopKeyValueIterable()) = 0;
nostd::shared_ptr<Logger> GetLogger(
nostd::string_view logger_name,
nostd::string_view library_name,
nostd::string_view library_version,
nostd::string_view schema_url,
std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes)
{
return GetLogger(logger_name, library_name, library_version, schema_url,
nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
attributes.begin(), attributes.end()});
}
template <class T,
nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr>
nostd::shared_ptr<Logger> GetLogger(nostd::string_view logger_name,
nostd::string_view library_name,
nostd::string_view library_version,
nostd::string_view schema_url,
const T &attributes)
{
return GetLogger(logger_name, library_name, library_version, schema_url,
common::KeyValueIterableView<T>(attributes));
}
};
} // namespace logs
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,204 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <chrono>
#include <memory>
#include <type_traits>
#include "opentelemetry/common/attribute_value.h"
#include "opentelemetry/common/key_value_iterable.h"
#include "opentelemetry/common/timestamp.h"
#include "opentelemetry/logs/event_id.h"
#include "opentelemetry/logs/log_record.h"
#include "opentelemetry/logs/severity.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/nostd/type_traits.h"
#include "opentelemetry/trace/span_context.h"
#include "opentelemetry/trace/span_id.h"
#include "opentelemetry/trace/trace_flags.h"
#include "opentelemetry/trace/trace_id.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace logs
{
namespace detail
{
template <class ValueType>
struct LogRecordSetterTrait;
template <>
struct LogRecordSetterTrait<Severity>
{
template <class ArgumentType>
inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
{
log_record->SetSeverity(std::forward<ArgumentType>(arg));
return log_record;
}
};
template <>
struct LogRecordSetterTrait<EventId>
{
template <class ArgumentType>
inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
{
log_record->SetEventId(arg.id_, nostd::string_view{arg.name_.get()});
return log_record;
}
};
template <>
struct LogRecordSetterTrait<trace::SpanContext>
{
template <class ArgumentType>
inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
{
log_record->SetSpanId(arg.span_id());
log_record->SetTraceId(arg.trace_id());
log_record->SetTraceFlags(arg.trace_flags());
return log_record;
}
};
template <>
struct LogRecordSetterTrait<trace::SpanId>
{
template <class ArgumentType>
inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
{
log_record->SetSpanId(std::forward<ArgumentType>(arg));
return log_record;
}
};
template <>
struct LogRecordSetterTrait<trace::TraceId>
{
template <class ArgumentType>
inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
{
log_record->SetTraceId(std::forward<ArgumentType>(arg));
return log_record;
}
};
template <>
struct LogRecordSetterTrait<trace::TraceFlags>
{
template <class ArgumentType>
inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
{
log_record->SetTraceFlags(std::forward<ArgumentType>(arg));
return log_record;
}
};
template <>
struct LogRecordSetterTrait<common::SystemTimestamp>
{
template <class ArgumentType>
inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
{
log_record->SetTimestamp(std::forward<ArgumentType>(arg));
return log_record;
}
};
template <>
struct LogRecordSetterTrait<std::chrono::system_clock::time_point>
{
template <class ArgumentType>
inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
{
log_record->SetTimestamp(common::SystemTimestamp(std::forward<ArgumentType>(arg)));
return log_record;
}
};
template <>
struct LogRecordSetterTrait<common::KeyValueIterable>
{
template <class ArgumentType>
inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
{
arg.ForEachKeyValue(
[&log_record](nostd::string_view key, common::AttributeValue value) noexcept {
log_record->SetAttribute(key, value);
return true;
});
return log_record;
}
};
template <class ValueType>
struct LogRecordSetterTrait
{
static_assert(!std::is_same<nostd::unique_ptr<LogRecord>, ValueType>::value &&
!std::is_same<std::unique_ptr<LogRecord>, ValueType>::value,
"unique_ptr<LogRecord> is not allowed, please use std::move()");
template <class ArgumentType,
nostd::enable_if_t<std::is_convertible<ArgumentType, nostd::string_view>::value ||
std::is_convertible<ArgumentType, common::AttributeValue>::value,
void> * = nullptr>
inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
{
log_record->SetBody(std::forward<ArgumentType>(arg));
return log_record;
}
template <class ArgumentType,
nostd::enable_if_t<std::is_base_of<common::KeyValueIterable, ArgumentType>::value, bool>
* = nullptr>
inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
{
return LogRecordSetterTrait<common::KeyValueIterable>::Set(log_record,
std::forward<ArgumentType>(arg));
}
template <class ArgumentType,
nostd::enable_if_t<common::detail::is_key_value_iterable<ArgumentType>::value, int> * =
nullptr>
inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
{
for (auto &argv : arg)
{
log_record->SetAttribute(argv.first, argv.second);
}
return log_record;
}
};
template <class ValueType, class... ArgumentType>
struct LogRecordHasType;
template <class ValueType>
struct LogRecordHasType<ValueType> : public std::false_type
{};
template <class ValueType, class TargetType, class... ArgumentType>
struct LogRecordHasType<ValueType, TargetType, ArgumentType...>
: public std::conditional<std::is_same<ValueType, TargetType>::value,
std::true_type,
LogRecordHasType<ValueType, ArgumentType...>>::type
{};
} // namespace detail
} // namespace logs
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,131 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
// Please refer to provider.h for documentation on how to obtain a Logger object.
//
// This file is part of the internal implementation of OpenTelemetry. Nothing in this file should be
// used directly. Please refer to logger.h for documentation on these interfaces.
#include "opentelemetry/logs/event_logger.h"
#include "opentelemetry/logs/event_logger_provider.h"
#include "opentelemetry/logs/logger.h"
#include "opentelemetry/logs/logger_provider.h"
#include "opentelemetry/nostd/shared_ptr.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/nostd/unique_ptr.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace common
{
class KeyValueIterable;
} // namespace common
namespace logs
{
/**
* No-op implementation of Logger. This class should not be used directly. It should only be
* instantiated using a LoggerProvider's GetLogger() call.
*/
class NoopLogger final : public Logger
{
public:
const nostd::string_view GetName() noexcept override { return "noop logger"; }
nostd::unique_ptr<LogRecord> CreateLogRecord() noexcept override
{
/*
* Do not return memory shared between threads,
* a `new` + `delete` for each noop record can not be avoided,
* due to the semantic of unique_ptr.
*/
return nostd::unique_ptr<LogRecord>(new NoopLogRecord());
}
using Logger::EmitLogRecord;
void EmitLogRecord(nostd::unique_ptr<LogRecord> &&) noexcept override {}
private:
class NoopLogRecord : public LogRecord
{
public:
NoopLogRecord() = default;
~NoopLogRecord() override = default;
void SetTimestamp(common::SystemTimestamp /* timestamp */) noexcept override {}
void SetObservedTimestamp(common::SystemTimestamp /* timestamp */) noexcept override {}
void SetSeverity(logs::Severity /* severity */) noexcept override {}
void SetBody(const common::AttributeValue & /* message */) noexcept override {}
void SetAttribute(nostd::string_view /* key */,
const common::AttributeValue & /* value */) noexcept override
{}
void SetEventId(int64_t /* id */, nostd::string_view /* name */) noexcept override {}
void SetTraceId(const trace::TraceId & /* trace_id */) noexcept override {}
void SetSpanId(const trace::SpanId & /* span_id */) noexcept override {}
void SetTraceFlags(const trace::TraceFlags & /* trace_flags */) noexcept override {}
};
};
/**
* No-op implementation of a LoggerProvider.
*/
class NoopLoggerProvider final : public LoggerProvider
{
public:
NoopLoggerProvider() : logger_{nostd::shared_ptr<NoopLogger>(new NoopLogger())} {}
nostd::shared_ptr<Logger> GetLogger(nostd::string_view /* logger_name */,
nostd::string_view /* library_name */,
nostd::string_view /* library_version */,
nostd::string_view /* schema_url */,
const common::KeyValueIterable & /* attributes */) override
{
return logger_;
}
private:
nostd::shared_ptr<Logger> logger_;
};
#if OPENTELEMETRY_ABI_VERSION_NO < 2
class NoopEventLogger final : public EventLogger
{
public:
NoopEventLogger() : logger_{nostd::shared_ptr<NoopLogger>(new NoopLogger())} {}
const nostd::string_view GetName() noexcept override { return "noop event logger"; }
nostd::shared_ptr<Logger> GetDelegateLogger() noexcept override { return logger_; }
void EmitEvent(nostd::string_view, nostd::unique_ptr<LogRecord> &&) noexcept override {}
private:
nostd::shared_ptr<Logger> logger_;
};
/**
* No-op implementation of a EventLoggerProvider.
*/
class NoopEventLoggerProvider final : public EventLoggerProvider
{
public:
NoopEventLoggerProvider() : event_logger_{nostd::shared_ptr<EventLogger>(new NoopEventLogger())}
{}
nostd::shared_ptr<EventLogger> CreateEventLogger(
nostd::shared_ptr<Logger> /*delegate_logger*/,
nostd::string_view /*event_domain*/) noexcept override
{
return event_logger_;
}
private:
nostd::shared_ptr<EventLogger> event_logger_;
};
#endif
} // namespace logs
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,100 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <mutex>
#include "opentelemetry/common/macros.h"
#include "opentelemetry/common/spin_lock_mutex.h"
#include "opentelemetry/logs/noop.h"
#include "opentelemetry/nostd/shared_ptr.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace logs
{
#if OPENTELEMETRY_ABI_VERSION_NO < 2
class EventLoggerProvider;
#endif
class LoggerProvider;
/**
* Stores the singleton global LoggerProvider.
*/
class OPENTELEMETRY_EXPORT Provider
{
public:
/**
* Returns the singleton LoggerProvider.
*
* By default, a no-op LoggerProvider is returned. This will never return a
* nullptr LoggerProvider.
*/
static nostd::shared_ptr<LoggerProvider> GetLoggerProvider() noexcept
{
std::lock_guard<common::SpinLockMutex> guard(GetLock());
return nostd::shared_ptr<LoggerProvider>(GetProvider());
}
/**
* Changes the singleton LoggerProvider.
*/
static void SetLoggerProvider(const nostd::shared_ptr<LoggerProvider> &tp) noexcept
{
std::lock_guard<common::SpinLockMutex> guard(GetLock());
GetProvider() = tp;
}
#if OPENTELEMETRY_ABI_VERSION_NO < 2
/**
* Returns the singleton EventLoggerProvider.
*
* By default, a no-op EventLoggerProvider is returned. This will never return a
* nullptr EventLoggerProvider.
*/
OPENTELEMETRY_DEPRECATED static nostd::shared_ptr<EventLoggerProvider>
GetEventLoggerProvider() noexcept
{
std::lock_guard<common::SpinLockMutex> guard(GetLock());
return nostd::shared_ptr<EventLoggerProvider>(GetEventProvider());
}
/**
* Changes the singleton EventLoggerProvider.
*/
OPENTELEMETRY_DEPRECATED static void SetEventLoggerProvider(
const nostd::shared_ptr<EventLoggerProvider> &tp) noexcept
{
std::lock_guard<common::SpinLockMutex> guard(GetLock());
GetEventProvider() = tp;
}
#endif
private:
OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr<LoggerProvider> &GetProvider() noexcept
{
static nostd::shared_ptr<LoggerProvider> provider(new NoopLoggerProvider);
return provider;
}
#if OPENTELEMETRY_ABI_VERSION_NO < 2
OPENTELEMETRY_DEPRECATED
OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr<EventLoggerProvider> &
GetEventProvider() noexcept
{
static nostd::shared_ptr<EventLoggerProvider> provider(new NoopEventLoggerProvider);
return provider;
}
#endif
OPENTELEMETRY_API_SINGLETON static common::SpinLockMutex &GetLock() noexcept
{
static common::SpinLockMutex lock;
return lock;
}
};
} // namespace logs
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,67 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <cstdint>
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace logs
{
/**
* Severity Levels assigned to log events, based on Log Data Model,
* with the addition of kInvalid (mapped to a severity number of 0).
*
* See
* https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#field-severitynumber
*/
enum class Severity : uint8_t
{
kInvalid = 0,
kTrace = 1,
kTrace2 = 2,
kTrace3 = 3,
kTrace4 = 4,
kDebug = 5,
kDebug2 = 6,
kDebug3 = 7,
kDebug4 = 8,
kInfo = 9,
kInfo2 = 10,
kInfo3 = 11,
kInfo4 = 12,
kWarn = 13,
kWarn2 = 14,
kWarn3 = 15,
kWarn4 = 16,
kError = 17,
kError2 = 18,
kError3 = 19,
kError4 = 20,
kFatal = 21,
kFatal2 = 22,
kFatal3 = 23,
kFatal4 = 24
};
const uint8_t kMaxSeverity = 255;
/**
* Mapping of the severity enum above, to a severity text string (in all caps).
* This severity text can be printed out by exporters. Capital letters follow the
* spec naming convention.
*
* Included to follow the specification's recommendation to print both
* severity number and text in each log record.
*/
const nostd::string_view SeverityNumToText[25] = {
"INVALID", "TRACE", "TRACE2", "TRACE3", "TRACE4", "DEBUG", "DEBUG2", "DEBUG3", "DEBUG4",
"INFO", "INFO2", "INFO3", "INFO4", "WARN", "WARN2", "WARN3", "WARN4", "ERROR",
"ERROR2", "ERROR3", "ERROR4", "FATAL", "FATAL2", "FATAL3", "FATAL4"};
} // namespace logs
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,33 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "opentelemetry/metrics/observer_result.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace metrics
{
using ObservableCallbackPtr = void (*)(ObserverResult, void *);
class ObservableInstrument
{
public:
ObservableInstrument() = default;
virtual ~ObservableInstrument() = default;
/**
* Sets up a function that will be called whenever a metric collection is initiated.
*/
virtual void AddCallback(ObservableCallbackPtr, void *state) noexcept = 0;
/**
* Remove a function that was configured to be called whenever a metric collection is initiated.
*/
virtual void RemoveCallback(ObservableCallbackPtr, void *state) noexcept = 0;
};
} // namespace metrics
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,174 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "opentelemetry/nostd/shared_ptr.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/nostd/unique_ptr.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace metrics
{
template <typename T>
class Counter;
template <typename T>
class Histogram;
template <typename T>
class UpDownCounter;
template <typename T>
class Gauge;
class ObservableInstrument;
/**
* Handles instrument creation and provides a facility for batch recording.
*
* This class provides methods to create new metric instruments, record a
* batch of values to a specified set of instruments, and collect
* measurements from all instruments.
*
*/
class Meter
{
public:
virtual ~Meter() = default;
/**
* Creates a Counter with the passed characteristics and returns a unique_ptr to that Counter.
*
* @param name the name of the new Counter.
* @param description a brief description of what the Counter is used for.
* @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html.
* @return a shared pointer to the created Counter.
*/
virtual nostd::unique_ptr<Counter<uint64_t>> CreateUInt64Counter(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept = 0;
virtual nostd::unique_ptr<Counter<double>> CreateDoubleCounter(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept = 0;
/**
* Creates a Asynchronous (Observable) counter with the passed characteristics and returns a
* shared_ptr to that Observable Counter
*
* @param name the name of the new Observable Counter.
* @param description a brief description of what the Observable Counter is used for.
* @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html.
*/
virtual nostd::shared_ptr<ObservableInstrument> CreateInt64ObservableCounter(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept = 0;
virtual nostd::shared_ptr<ObservableInstrument> CreateDoubleObservableCounter(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept = 0;
/**
* Creates a Histogram with the passed characteristics and returns a unique_ptr to that Histogram.
*
* @param name the name of the new Histogram.
* @param description a brief description of what the Histogram is used for.
* @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html.
* @return a shared pointer to the created Histogram.
*/
virtual nostd::unique_ptr<Histogram<uint64_t>> CreateUInt64Histogram(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept = 0;
virtual nostd::unique_ptr<Histogram<double>> CreateDoubleHistogram(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept = 0;
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
/**
* Creates a Gauge with the passed characteristics and returns a unique_ptr to that Gauge.
*
* @param name the name of the new Gauge.
* @param description a brief description of what the Gauge is used for.
* @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html.
* @return a unique pointer to the created Gauge.
*/
virtual nostd::unique_ptr<Gauge<int64_t>> CreateInt64Gauge(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept = 0;
virtual nostd::unique_ptr<Gauge<double>> CreateDoubleGauge(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept = 0;
#endif
/**
* Creates a Asynchronous (Observable) Gauge with the passed characteristics and returns a
* shared_ptr to that Observable Gauge
*
* @param name the name of the new Observable Gauge.
* @param description a brief description of what the Observable Gauge is used for.
* @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html.
*/
virtual nostd::shared_ptr<ObservableInstrument> CreateInt64ObservableGauge(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept = 0;
virtual nostd::shared_ptr<ObservableInstrument> CreateDoubleObservableGauge(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept = 0;
/**
* Creates an UpDownCounter with the passed characteristics and returns a unique_ptr to that
* UpDownCounter.
*
* @param name the name of the new UpDownCounter.
* @param description a brief description of what the UpDownCounter is used for.
* @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html.
* @return a shared pointer to the created UpDownCounter.
*/
virtual nostd::unique_ptr<UpDownCounter<int64_t>> CreateInt64UpDownCounter(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept = 0;
virtual nostd::unique_ptr<UpDownCounter<double>> CreateDoubleUpDownCounter(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept = 0;
/**
* Creates a Asynchronous (Observable) UpDownCounter with the passed characteristics and returns
* a shared_ptr to that Observable UpDownCounter
*
* @param name the name of the new Observable UpDownCounter.
* @param description a brief description of what the Observable UpDownCounter is used for.
* @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html.
*/
virtual nostd::shared_ptr<ObservableInstrument> CreateInt64ObservableUpDownCounter(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept = 0;
virtual nostd::shared_ptr<ObservableInstrument> CreateDoubleObservableUpDownCounter(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept = 0;
};
} // namespace metrics
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,148 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "opentelemetry/common/key_value_iterable.h"
#include "opentelemetry/common/key_value_iterable_view.h"
#include "opentelemetry/nostd/shared_ptr.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/nostd/type_traits.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace metrics
{
class Meter;
/**
* Creates new Meter instances.
*/
class MeterProvider
{
public:
virtual ~MeterProvider() = default;
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
/**
* Gets or creates a named Meter instance (ABI).
*
* @since ABI_VERSION 2
*
* @param[in] name Meter instrumentation scope
* @param[in] version Instrumentation scope version
* @param[in] schema_url Instrumentation scope schema URL
* @param[in] attributes Instrumentation scope attributes (optional, may be nullptr)
*/
virtual nostd::shared_ptr<Meter> GetMeter(
nostd::string_view name,
nostd::string_view version,
nostd::string_view schema_url,
const common::KeyValueIterable *attributes) noexcept = 0;
/**
* Gets or creates a named Meter instance (API helper).
*
* @since ABI_VERSION 2
*
* @param[in] name Meter instrumentation scope
* @param[in] version Instrumentation scope version, optional
* @param[in] schema_url Instrumentation scope schema URL, optional
*/
nostd::shared_ptr<Meter> GetMeter(nostd::string_view name,
nostd::string_view version = "",
nostd::string_view schema_url = "")
{
return GetMeter(name, version, schema_url, nullptr);
}
/**
* Gets or creates a named Meter instance (API helper).
*
* @since ABI_VERSION 2
*
* @param[in] name Meter instrumentation scope
* @param[in] version Instrumentation scope version
* @param[in] schema_url Instrumentation scope schema URL
* @param[in] attributes Instrumentation scope attributes
*/
nostd::shared_ptr<Meter> GetMeter(
nostd::string_view name,
nostd::string_view version,
nostd::string_view schema_url,
std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes)
{
/* Build a container from std::initializer_list. */
nostd::span<const std::pair<nostd::string_view, common::AttributeValue>> attributes_span{
attributes.begin(), attributes.end()};
/* Build a view on the container. */
common::KeyValueIterableView<
nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>>
iterable_attributes{attributes_span};
/* Add attributes using the view. */
return GetMeter(name, version, schema_url, &iterable_attributes);
}
/**
* Gets or creates a named Meter instance (API helper).
*
* @since ABI_VERSION 2
*
* @param[in] name Meter instrumentation scope
* @param[in] version Instrumentation scope version
* @param[in] schema_url Instrumentation scope schema URL
* @param[in] attributes Instrumentation scope attributes container
*/
template <class T,
nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr>
nostd::shared_ptr<Meter> GetMeter(nostd::string_view name,
nostd::string_view version,
nostd::string_view schema_url,
const T &attributes)
{
/* Build a view on the container. */
common::KeyValueIterableView<T> iterable_attributes(attributes);
/* Add attributes using the view. */
return GetMeter(name, version, schema_url, &iterable_attributes);
}
#else
/**
* Gets or creates a named Meter instance (ABI)
*
* @since ABI_VERSION 1
*
* @param[in] name Meter instrumentation scope
* @param[in] version Instrumentation scope version, optional
* @param[in] schema_url Instrumentation scope schema URL, optional
*/
virtual nostd::shared_ptr<Meter> GetMeter(nostd::string_view name,
nostd::string_view version = "",
nostd::string_view schema_url = "") noexcept = 0;
#endif
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
/**
* Remove a named Meter instance (ABI).
*
* This API is experimental, see
* https://github.com/open-telemetry/opentelemetry-specification/issues/2232
*
* @since ABI_VERSION 2
*
* @param[in] name Meter instrumentation scope
* @param[in] version Instrumentation scope version, optional
* @param[in] schema_url Instrumentation scope schema URL, optional
*/
virtual void RemoveMeter(nostd::string_view name,
nostd::string_view version = "",
nostd::string_view schema_url = "") noexcept = 0;
#endif
};
} // namespace metrics
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,271 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "opentelemetry/metrics/async_instruments.h"
#include "opentelemetry/metrics/meter.h"
#include "opentelemetry/metrics/meter_provider.h"
#include "opentelemetry/metrics/observer_result.h"
#include "opentelemetry/metrics/sync_instruments.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace metrics
{
template <class T>
class NoopCounter : public Counter<T>
{
public:
NoopCounter(nostd::string_view /* name */,
nostd::string_view /* description */,
nostd::string_view /* unit */) noexcept
{}
void Add(T /* value */) noexcept override {}
void Add(T /* value */, const context::Context & /* context */) noexcept override {}
void Add(T /* value */, const common::KeyValueIterable & /* attributes */) noexcept override {}
void Add(T /* value */,
const common::KeyValueIterable & /* attributes */,
const context::Context & /* context */) noexcept override
{}
};
template <class T>
class NoopHistogram : public Histogram<T>
{
public:
NoopHistogram(nostd::string_view /* name */,
nostd::string_view /* description */,
nostd::string_view /* unit */) noexcept
{}
void Record(T /* value */, const context::Context & /* context */) noexcept override {}
void Record(T /* value */,
const common::KeyValueIterable & /* attributes */,
const context::Context & /* context */) noexcept override
{}
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
void Record(T /*value*/,
const opentelemetry::common::KeyValueIterable & /*attributes*/) noexcept override
{}
void Record(T /*value*/) noexcept override {}
#endif
};
template <class T>
class NoopUpDownCounter : public UpDownCounter<T>
{
public:
NoopUpDownCounter(nostd::string_view /* name */,
nostd::string_view /* description */,
nostd::string_view /* unit */) noexcept
{}
~NoopUpDownCounter() override = default;
void Add(T /* value */) noexcept override {}
void Add(T /* value */, const context::Context & /* context */) noexcept override {}
void Add(T /* value */, const common::KeyValueIterable & /* attributes */) noexcept override {}
void Add(T /* value */,
const common::KeyValueIterable & /* attributes */,
const context::Context & /* context */) noexcept override
{}
};
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
template <class T>
class NoopGauge : public Gauge<T>
{
public:
NoopGauge(nostd::string_view /* name */,
nostd::string_view /* description */,
nostd::string_view /* unit */) noexcept
{}
~NoopGauge() override = default;
void Record(T /* value */) noexcept override {}
void Record(T /* value */, const context::Context & /* context */) noexcept override {}
void Record(T /* value */, const common::KeyValueIterable & /* attributes */) noexcept override {}
void Record(T /* value */,
const common::KeyValueIterable & /* attributes */,
const context::Context & /* context */) noexcept override
{}
};
#endif
class NoopObservableInstrument : public ObservableInstrument
{
public:
NoopObservableInstrument(nostd::string_view /* name */,
nostd::string_view /* description */,
nostd::string_view /* unit */) noexcept
{}
void AddCallback(ObservableCallbackPtr, void * /* state */) noexcept override {}
void RemoveCallback(ObservableCallbackPtr, void * /* state */) noexcept override {}
};
/**
* No-op implementation of Meter.
*/
class NoopMeter final : public Meter
{
public:
nostd::unique_ptr<Counter<uint64_t>> CreateUInt64Counter(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept override
{
return nostd::unique_ptr<Counter<uint64_t>>{new NoopCounter<uint64_t>(name, description, unit)};
}
nostd::unique_ptr<Counter<double>> CreateDoubleCounter(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept override
{
return nostd::unique_ptr<Counter<double>>{new NoopCounter<double>(name, description, unit)};
}
nostd::shared_ptr<ObservableInstrument> CreateInt64ObservableCounter(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept override
{
return nostd::shared_ptr<ObservableInstrument>(
new NoopObservableInstrument(name, description, unit));
}
nostd::shared_ptr<ObservableInstrument> CreateDoubleObservableCounter(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept override
{
return nostd::shared_ptr<ObservableInstrument>(
new NoopObservableInstrument(name, description, unit));
}
nostd::unique_ptr<Histogram<uint64_t>> CreateUInt64Histogram(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept override
{
return nostd::unique_ptr<Histogram<uint64_t>>{
new NoopHistogram<uint64_t>(name, description, unit)};
}
nostd::unique_ptr<Histogram<double>> CreateDoubleHistogram(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept override
{
return nostd::unique_ptr<Histogram<double>>{new NoopHistogram<double>(name, description, unit)};
}
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
nostd::unique_ptr<Gauge<int64_t>> CreateInt64Gauge(nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept override
{
return nostd::unique_ptr<Gauge<int64_t>>{new NoopGauge<int64_t>(name, description, unit)};
}
nostd::unique_ptr<Gauge<double>> CreateDoubleGauge(nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept override
{
return nostd::unique_ptr<Gauge<double>>{new NoopGauge<double>(name, description, unit)};
}
#endif
nostd::shared_ptr<ObservableInstrument> CreateInt64ObservableGauge(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept override
{
return nostd::shared_ptr<ObservableInstrument>(
new NoopObservableInstrument(name, description, unit));
}
nostd::shared_ptr<ObservableInstrument> CreateDoubleObservableGauge(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept override
{
return nostd::shared_ptr<ObservableInstrument>(
new NoopObservableInstrument(name, description, unit));
}
nostd::unique_ptr<UpDownCounter<int64_t>> CreateInt64UpDownCounter(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept override
{
return nostd::unique_ptr<UpDownCounter<int64_t>>{
new NoopUpDownCounter<int64_t>(name, description, unit)};
}
nostd::unique_ptr<UpDownCounter<double>> CreateDoubleUpDownCounter(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept override
{
return nostd::unique_ptr<UpDownCounter<double>>{
new NoopUpDownCounter<double>(name, description, unit)};
}
nostd::shared_ptr<ObservableInstrument> CreateInt64ObservableUpDownCounter(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept override
{
return nostd::shared_ptr<ObservableInstrument>(
new NoopObservableInstrument(name, description, unit));
}
nostd::shared_ptr<ObservableInstrument> CreateDoubleObservableUpDownCounter(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept override
{
return nostd::shared_ptr<ObservableInstrument>(
new NoopObservableInstrument(name, description, unit));
}
};
/**
* No-op implementation of a MeterProvider.
*/
class NoopMeterProvider final : public MeterProvider
{
public:
NoopMeterProvider() : meter_{nostd::shared_ptr<Meter>(new NoopMeter)} {}
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
nostd::shared_ptr<Meter> GetMeter(
nostd::string_view /* name */,
nostd::string_view /* version */,
nostd::string_view /* schema_url */,
const common::KeyValueIterable * /* attributes */) noexcept override
{
return meter_;
}
#else
nostd::shared_ptr<Meter> GetMeter(nostd::string_view /* name */,
nostd::string_view /* version */,
nostd::string_view /* schema_url */) noexcept override
{
return meter_;
}
#endif
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
void RemoveMeter(nostd::string_view /* name */,
nostd::string_view /* version */,
nostd::string_view /* schema_url */) noexcept override
{}
#endif
private:
nostd::shared_ptr<Meter> meter_;
};
} // namespace metrics
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,54 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "opentelemetry/common/attribute_value.h"
#include "opentelemetry/common/key_value_iterable_view.h"
#include "opentelemetry/nostd/shared_ptr.h"
#include "opentelemetry/nostd/span.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/nostd/type_traits.h"
#include "opentelemetry/nostd/variant.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace metrics
{
/**
* ObserverResultT class is necessary for the callback recording asynchronous
* instrument use.
*/
template <class T>
class ObserverResultT
{
public:
virtual ~ObserverResultT() = default;
virtual void Observe(T value) noexcept = 0;
virtual void Observe(T value, const common::KeyValueIterable &attributes) noexcept = 0;
template <class U,
nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr>
void Observe(T value, const U &attributes) noexcept
{
this->Observe(value, common::KeyValueIterableView<U>{attributes});
}
void Observe(T value,
std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>
attributes) noexcept
{
this->Observe(value, nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
attributes.begin(), attributes.end()});
}
};
using ObserverResult = nostd::variant<nostd::shared_ptr<ObserverResultT<int64_t>>,
nostd::shared_ptr<ObserverResultT<double>>>;
} // namespace metrics
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,60 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <mutex>
#include "opentelemetry/common/spin_lock_mutex.h"
#include "opentelemetry/metrics/meter_provider.h"
#include "opentelemetry/metrics/noop.h"
#include "opentelemetry/nostd/shared_ptr.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace metrics
{
/**
* Stores the singleton global MeterProvider.
*/
class Provider
{
public:
/**
* Returns the singleton MeterProvider.
*
* By default, a no-op MeterProvider is returned. This will never return a
* nullptr MeterProvider.
*/
static nostd::shared_ptr<MeterProvider> GetMeterProvider() noexcept
{
std::lock_guard<common::SpinLockMutex> guard(GetLock());
return nostd::shared_ptr<MeterProvider>(GetProvider());
}
/**
* Changes the singleton MeterProvider.
*/
static void SetMeterProvider(const nostd::shared_ptr<MeterProvider> &tp) noexcept
{
std::lock_guard<common::SpinLockMutex> guard(GetLock());
GetProvider() = tp;
}
private:
OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr<MeterProvider> &GetProvider() noexcept
{
static nostd::shared_ptr<MeterProvider> provider(new NoopMeterProvider);
return provider;
}
OPENTELEMETRY_API_SINGLETON static common::SpinLockMutex &GetLock() noexcept
{
static common::SpinLockMutex lock;
return lock;
}
};
} // namespace metrics
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,328 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "opentelemetry/common/attribute_value.h"
#include "opentelemetry/common/key_value_iterable_view.h"
#include "opentelemetry/context/context.h"
#include "opentelemetry/nostd/span.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/nostd/type_traits.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace metrics
{
class SynchronousInstrument
{
public:
SynchronousInstrument() = default;
virtual ~SynchronousInstrument() = default;
};
/* A Counter instrument that adds values. */
template <class T>
class Counter : public SynchronousInstrument
{
public:
/**
* Record a value
*
* @param value The increment amount. MUST be non-negative.
*/
virtual void Add(T value) noexcept = 0;
/**
* Record a value
*
* @param value The increment amount. MUST be non-negative.
* @param context The explicit context to associate with this measurement.
*/
virtual void Add(T value, const context::Context &context) noexcept = 0;
/**
* Record a value with a set of attributes.
*
* @param value The increment amount. MUST be non-negative.
* @param attributes A set of attributes to associate with the value.
*/
virtual void Add(T value, const common::KeyValueIterable &attributes) noexcept = 0;
/**
* Record a value with a set of attributes.
*
* @param value The increment amount. MUST be non-negative.
* @param attributes A set of attributes to associate with the value.
* @param context The explicit context to associate with this measurement.
*/
virtual void Add(T value,
const common::KeyValueIterable &attributes,
const context::Context &context) noexcept = 0;
template <class U,
nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr>
void Add(T value, const U &attributes) noexcept
{
this->Add(value, common::KeyValueIterableView<U>{attributes});
}
template <class U,
nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr>
void Add(T value, const U &attributes, const context::Context &context) noexcept
{
this->Add(value, common::KeyValueIterableView<U>{attributes}, context);
}
void Add(T value,
std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>
attributes) noexcept
{
this->Add(value, nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
attributes.begin(), attributes.end()});
}
void Add(T value,
std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes,
const context::Context &context) noexcept
{
this->Add(value,
nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
attributes.begin(), attributes.end()},
context);
}
};
/** A histogram instrument that records values. */
template <class T>
class Histogram : public SynchronousInstrument
{
public:
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
/**
* @since ABI_VERSION 2
* Records a value.
*
* @param value The measurement value. MUST be non-negative.
*/
virtual void Record(T value) noexcept = 0;
/**
* @since ABI_VERSION 2
* Records a value with a set of attributes.
*
* @param value The measurement value. MUST be non-negative.
* @param attribute A set of attributes to associate with the value.
*/
virtual void Record(T value, const common::KeyValueIterable &attribute) noexcept = 0;
template <class U,
nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr>
void Record(T value, const U &attributes) noexcept
{
this->Record(value, common::KeyValueIterableView<U>{attributes});
}
void Record(T value,
std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>
attributes) noexcept
{
this->Record(value, nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
attributes.begin(), attributes.end()});
}
#endif
/**
* Records a value.
*
* @param value The measurement value. MUST be non-negative.
* @param context The explicit context to associate with this measurement.
*/
virtual void Record(T value, const context::Context &context) noexcept = 0;
/**
* Records a value with a set of attributes.
*
* @param value The measurement value. MUST be non-negative.
* @param attributes A set of attributes to associate with the value..
* @param context The explicit context to associate with this measurement.
*/
virtual void Record(T value,
const common::KeyValueIterable &attributes,
const context::Context &context) noexcept = 0;
template <class U,
nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr>
void Record(T value, const U &attributes, const context::Context &context) noexcept
{
this->Record(value, common::KeyValueIterableView<U>{attributes}, context);
}
void Record(
T value,
std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes,
const context::Context &context) noexcept
{
this->Record(value,
nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
attributes.begin(), attributes.end()},
context);
}
};
/** An up-down-counter instrument that adds or reduce values. */
template <class T>
class UpDownCounter : public SynchronousInstrument
{
public:
/**
* Record a value.
*
* @param value The increment amount. May be positive, negative or zero.
*/
virtual void Add(T value) noexcept = 0;
/**
* Record a value.
*
* @param value The increment amount. May be positive, negative or zero.
* @param context The explicit context to associate with this measurement.
*/
virtual void Add(T value, const context::Context &context) noexcept = 0;
/**
* Record a value with a set of attributes.
*
* @param value The increment amount. May be positive, negative or zero.
* @param attributes A set of attributes to associate with the count.
*/
virtual void Add(T value, const common::KeyValueIterable &attributes) noexcept = 0;
/**
* Record a value with a set of attributes.
*
* @param value The increment amount. May be positive, negative or zero.
* @param attributes A set of attributes to associate with the count.
* @param context The explicit context to associate with this measurement.
*/
virtual void Add(T value,
const common::KeyValueIterable &attributes,
const context::Context &context) noexcept = 0;
template <class U,
nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr>
void Add(T value, const U &attributes) noexcept
{
this->Add(value, common::KeyValueIterableView<U>{attributes});
}
template <class U,
nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr>
void Add(T value, const U &attributes, const context::Context &context) noexcept
{
this->Add(value, common::KeyValueIterableView<U>{attributes}, context);
}
void Add(T value,
std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>
attributes) noexcept
{
this->Add(value, nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
attributes.begin(), attributes.end()});
}
void Add(T value,
std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes,
const context::Context &context) noexcept
{
this->Add(value,
nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
attributes.begin(), attributes.end()},
context);
}
};
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
/* A Gauge instrument that records values. */
template <class T>
class Gauge : public SynchronousInstrument
{
public:
/**
* Record a value
*
* @param value The measurement value. May be positive, negative or zero.
*/
virtual void Record(T value) noexcept = 0;
/**
* Record a value
*
* @param value The measurement value. May be positive, negative or zero.
* @param context The explicit context to associate with this measurement.
*/
virtual void Record(T value, const context::Context &context) noexcept = 0;
/**
* Record a value with a set of attributes.
*
* @param value The measurement value. May be positive, negative or zero.
* @param attributes A set of attributes to associate with the value.
*/
virtual void Record(T value, const common::KeyValueIterable &attributes) noexcept = 0;
/**
* Record a value with a set of attributes.
*
* @param value The measurement value. May be positive, negative or zero.
* @param attributes A set of attributes to associate with the value.
* @param context The explicit context to associate with this measurement.
*/
virtual void Record(T value,
const common::KeyValueIterable &attributes,
const context::Context &context) noexcept = 0;
template <class U,
nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr>
void Record(T value, const U &attributes) noexcept
{
this->Record(value, common::KeyValueIterableView<U>{attributes});
}
template <class U,
nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr>
void Record(T value, const U &attributes, const context::Context &context) noexcept
{
this->Record(value, common::KeyValueIterableView<U>{attributes}, context);
}
void Record(T value,
std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>
attributes) noexcept
{
this->Record(value, nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
attributes.begin(), attributes.end()});
}
void Record(
T value,
std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes,
const context::Context &context) noexcept
{
this->Record(value,
nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
attributes.begin(), attributes.end()},
context);
}
};
#endif
} // namespace metrics
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,21 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <type_traits>
#include "opentelemetry/nostd/utility.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace nostd
{
namespace detail
{
template <bool... Bs>
using all = std::is_same<integer_sequence<bool, true, Bs...>, integer_sequence<bool, Bs..., true>>;
} // namespace detail
} // namespace nostd
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,16 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <type_traits>
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace nostd
{
template <class T>
using decay_t = typename std::decay<T>::type;
} // namespace nostd
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,20 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <type_traits>
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace nostd
{
namespace detail
{
template <typename T, bool>
struct dependent_type : T
{};
} // namespace detail
} // namespace nostd
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,66 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <utility>
#include "opentelemetry/version.h"
#define OPENTELEMETRY_RETURN(...) \
noexcept(noexcept(__VA_ARGS__))->decltype(__VA_ARGS__) \
{ \
return __VA_ARGS__; \
}
OPENTELEMETRY_BEGIN_NAMESPACE
namespace nostd
{
namespace detail
{
struct equal_to
{
template <typename Lhs, typename Rhs>
inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
OPENTELEMETRY_RETURN(std::forward<Lhs>(lhs) == std::forward<Rhs>(rhs))
};
struct not_equal_to
{
template <typename Lhs, typename Rhs>
inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
OPENTELEMETRY_RETURN(std::forward<Lhs>(lhs) != std::forward<Rhs>(rhs))
};
struct less
{
template <typename Lhs, typename Rhs>
inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
OPENTELEMETRY_RETURN(std::forward<Lhs>(lhs) < std::forward<Rhs>(rhs))
};
struct greater
{
template <typename Lhs, typename Rhs>
inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
OPENTELEMETRY_RETURN(std::forward<Lhs>(lhs) > std::forward<Rhs>(rhs))
};
struct less_equal
{
template <typename Lhs, typename Rhs>
inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
OPENTELEMETRY_RETURN(std::forward<Lhs>(lhs) <= std::forward<Rhs>(rhs))
};
struct greater_equal
{
template <typename Lhs, typename Rhs>
inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
OPENTELEMETRY_RETURN(std::forward<Lhs>(lhs) >= std::forward<Rhs>(rhs))
};
} // namespace detail
} // namespace nostd
OPENTELEMETRY_END_NAMESPACE
#undef OPENTELEMETRY_RETURN

View file

@ -0,0 +1,163 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <type_traits>
#include <utility>
#include "opentelemetry/nostd/detail/decay.h"
#include "opentelemetry/nostd/detail/void.h"
#include "opentelemetry/version.h"
#define OPENTELEMETRY_RETURN(...) \
noexcept(noexcept(__VA_ARGS__))->decltype(__VA_ARGS__) \
{ \
return __VA_ARGS__; \
}
OPENTELEMETRY_BEGIN_NAMESPACE
namespace nostd
{
namespace detail
{
template <typename T>
struct is_reference_wrapper : std::false_type
{};
template <typename T>
struct is_reference_wrapper<std::reference_wrapper<T>> : std::true_type
{};
template <bool, int>
struct Invoke;
template <>
struct Invoke<true /* pmf */, 0 /* is_base_of */>
{
template <typename R, typename T, typename Arg, typename... Args>
inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&...args)
OPENTELEMETRY_RETURN((std::forward<Arg>(arg).*pmf)(std::forward<Args>(args)...))
};
template <>
struct Invoke<true /* pmf */, 1 /* is_reference_wrapper */>
{
template <typename R, typename T, typename Arg, typename... Args>
inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&...args)
OPENTELEMETRY_RETURN((std::forward<Arg>(arg).get().*pmf)(std::forward<Args>(args)...))
};
template <>
struct Invoke<true /* pmf */, 2 /* otherwise */>
{
template <typename R, typename T, typename Arg, typename... Args>
inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&...args)
OPENTELEMETRY_RETURN(((*std::forward<Arg>(arg)).*pmf)(std::forward<Args>(args)...))
};
template <>
struct Invoke<false /* pmo */, 0 /* is_base_of */>
{
template <typename R, typename T, typename Arg>
inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
OPENTELEMETRY_RETURN(std::forward<Arg>(arg).*pmo)
};
template <>
struct Invoke<false /* pmo */, 1 /* is_reference_wrapper */>
{
template <typename R, typename T, typename Arg>
inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
OPENTELEMETRY_RETURN(std::forward<Arg>(arg).get().*pmo)
};
template <>
struct Invoke<false /* pmo */, 2 /* otherwise */>
{
template <typename R, typename T, typename Arg>
inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
OPENTELEMETRY_RETURN((*std::forward<Arg>(arg)).*pmo)
};
template <typename R, typename T, typename Arg, typename... Args>
inline constexpr auto invoke_impl(R T::*f, Arg &&arg, Args &&...args) OPENTELEMETRY_RETURN(
Invoke<std::is_function<R>::value,
(std::is_base_of<T, decay_t<Arg>>::value ? 0
: is_reference_wrapper<decay_t<Arg>>::value ? 1
: 2)>::invoke(f,
std::forward<Arg>(arg),
std::forward<Args>(args)...))
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable : 4100)
#endif
template <typename F, typename... Args>
inline constexpr auto invoke_impl(F &&f, Args &&...args)
OPENTELEMETRY_RETURN(std::forward<F>(f)(std::forward<Args>(args)...))
#ifdef _MSC_VER
# pragma warning(pop)
#endif
} // namespace detail
/* clang-format off */
template <typename F, typename... Args>
inline constexpr auto invoke(F &&f, Args &&... args)
OPENTELEMETRY_RETURN(detail::invoke_impl(std::forward<F>(f), std::forward<Args>(args)...))
namespace detail
/* clang-format on */
{
template <typename Void, typename, typename...>
struct invoke_result
{};
template <typename F, typename... Args>
struct invoke_result<void_t<decltype(nostd::invoke(std::declval<F>(), std::declval<Args>()...))>,
F, Args...>
{
using type = decltype(nostd::invoke(std::declval<F>(), std::declval<Args>()...));
};
} // namespace detail
template <typename F, typename... Args>
using invoke_result = detail::invoke_result<void, F, Args...>;
template <typename F, typename... Args>
using invoke_result_t = typename invoke_result<F, Args...>::type;
namespace detail
{
template <typename Void, typename, typename...>
struct is_invocable : std::false_type
{};
template <typename F, typename... Args>
struct is_invocable<void_t<invoke_result_t<F, Args...>>, F, Args...> : std::true_type
{};
template <typename Void, typename, typename, typename...>
struct is_invocable_r : std::false_type
{};
template <typename R, typename F, typename... Args>
struct is_invocable_r<void_t<invoke_result_t<F, Args...>>, R, F, Args...>
: std::is_convertible<invoke_result_t<F, Args...>, R>
{};
} // namespace detail
template <typename F, typename... Args>
using is_invocable = detail::is_invocable<void, F, Args...>;
template <typename R, typename F, typename... Args>
using is_invocable_r = detail::is_invocable_r<void, R, F, Args...>;
} // namespace nostd
OPENTELEMETRY_END_NAMESPACE
#undef OPENTELEMETRY_RETURN

View file

@ -0,0 +1,75 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <type_traits>
#include "opentelemetry/nostd/type_traits.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace nostd
{
namespace detail
{
enum class Trait
{
TriviallyAvailable,
Available,
Unavailable
};
template <typename T,
template <typename>
class IsTriviallyAvailable,
template <typename>
class IsAvailable>
inline constexpr Trait trait()
{
return IsTriviallyAvailable<T>::value ? Trait::TriviallyAvailable
: IsAvailable<T>::value ? Trait::Available
: Trait::Unavailable;
}
inline constexpr Trait common_trait_impl(Trait result)
{
return result;
}
template <typename... Traits>
inline constexpr Trait common_trait_impl(Trait result, Trait t, Traits... ts)
{
return static_cast<int>(t) > static_cast<int>(result) ? common_trait_impl(t, ts...)
: common_trait_impl(result, ts...);
}
template <typename... Traits>
inline constexpr Trait common_trait(Traits... ts)
{
return common_trait_impl(Trait::TriviallyAvailable, ts...);
}
template <typename... Ts>
struct traits
{
static constexpr Trait copy_constructible_trait =
common_trait(trait<Ts, is_trivially_copy_constructible, std::is_copy_constructible>()...);
static constexpr Trait move_constructible_trait =
common_trait(trait<Ts, is_trivially_move_constructible, std::is_move_constructible>()...);
static constexpr Trait copy_assignable_trait =
common_trait(copy_constructible_trait,
trait<Ts, is_trivially_copy_assignable, std::is_copy_assignable>()...);
static constexpr Trait move_assignable_trait =
common_trait(move_constructible_trait,
trait<Ts, is_trivially_move_assignable, std::is_move_assignable>()...);
static constexpr Trait destructible_trait =
common_trait(trait<Ts, std::is_trivially_destructible, std::is_destructible>()...);
};
} // namespace detail
} // namespace nostd
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,53 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <cstddef>
#include <type_traits>
#include "opentelemetry/nostd/utility.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace nostd
{
namespace detail
{
template <std::size_t N>
using size_constant = std::integral_constant<std::size_t, N>;
template <std::size_t I, typename T>
struct indexed_type : size_constant<I>
{
using type = T;
};
template <std::size_t I, typename... Ts>
struct type_pack_element_impl
{
private:
template <typename>
struct set;
template <std::size_t... Is>
struct set<index_sequence<Is...>> : indexed_type<Is, Ts>...
{};
template <typename T>
inline static std::enable_if<true, T> impl(indexed_type<I, T>);
inline static std::enable_if<false> impl(...);
public:
using type = decltype(impl(set<index_sequence_for<Ts...>>{}));
};
template <std::size_t I, typename... Ts>
using type_pack_element = typename type_pack_element_impl<I, Ts...>::type;
template <std::size_t I, typename... Ts>
using type_pack_element_t = typename type_pack_element<I, Ts...>::type;
} // namespace detail
} // namespace nostd
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,14 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace nostd
{
struct valueless_t
{};
} // namespace nostd
OPENTELEMETRY_END_NAMESPACE

View file

@ -0,0 +1,40 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <type_traits>
#include "opentelemetry/nostd/detail/type_pack_element.h"
#include "opentelemetry/nostd/detail/variant_fwd.h"
#include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace nostd
{
template <std::size_t I, typename T>
struct variant_alternative;
template <std::size_t I, typename T>
using variant_alternative_t = typename variant_alternative<I, T>::type;
template <std::size_t I, typename T>
struct variant_alternative<I, const T> : std::add_const<variant_alternative_t<I, T>>
{};
template <std::size_t I, typename T>
struct variant_alternative<I, volatile T> : std::add_volatile<variant_alternative_t<I, T>>
{};
template <std::size_t I, typename T>
struct variant_alternative<I, const volatile T> : std::add_cv<variant_alternative_t<I, T>>
{};
template <std::size_t I, typename... Ts>
struct variant_alternative<I, variant<Ts...>>
{
static_assert(I < sizeof...(Ts), "index out of bounds in `std::variant_alternative<>`");
using type = detail::type_pack_element_t<I, Ts...>;
};
} // namespace nostd
OPENTELEMETRY_END_NAMESPACE

Some files were not shown because too many files have changed in this diff Show more