diff --git a/pubsub-open-telemetry/.bazelrc b/pubsub-open-telemetry/.bazelrc new file mode 100644 index 0000000..b86565f --- /dev/null +++ b/pubsub-open-telemetry/.bazelrc @@ -0,0 +1,29 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +# Use host-OS-specific config lines from bazelrc files. +build --enable_platform_specific_config=true + +# The project requires C++ >= 14. By default Bazel adds `-std=c++0x` which +# disables C++14 features, even if the compilers defaults to C++ >= 14 +build:linux --cxxopt=-std=c++14 +build:macos --cxxopt=-std=c++14 + +# Do not create the convenience links. They are inconvenient when the build +# runs inside a docker image. +build --experimental_convenience_symlinks=ignore + +# Enable OpenTelemetry tracing instrumentation for google-cloud-cpp. +build --@io_opentelemetry_cpp//api:with_abseil +build --@google_cloud_cpp//:enable_opentelemetry diff --git a/pubsub-open-telemetry/BUILD.bazel b/pubsub-open-telemetry/BUILD.bazel new file mode 100644 index 0000000..ff89546 --- /dev/null +++ b/pubsub-open-telemetry/BUILD.bazel @@ -0,0 +1,26 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +package(default_visibility = ["//visibility:private"]) + +licenses(["notice"]) # Apache 2.0 + +cc_binary( + name = "quickstart", + srcs = ["quickstart.cc"], + deps = [ + "@google_cloud_cpp//:opentelemetry", + "@google_cloud_cpp//:pubsub", + ], +) diff --git a/pubsub-open-telemetry/CMakeLists.txt b/pubsub-open-telemetry/CMakeLists.txt new file mode 100644 index 0000000..33e8be4 --- /dev/null +++ b/pubsub-open-telemetry/CMakeLists.txt @@ -0,0 +1,30 @@ +# ~~~ +# Copyright 2023 Google LLC +# +# 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. +# ~~~ + +cmake_minimum_required(VERSION 3.20) + +# Define the project name and where to report bugs. +set(PACKAGE_BUGREPORT + "https://github.com/GoogleCloudPlatform/cpp-samples/issues") +project(pubsub-open-telemetry CXX) + +find_package(google_cloud_cpp_pubsub CONFIG REQUIRED) +find_package(google_cloud_cpp_opentelemetry CONFIG REQUIRED) + +add_executable(quickstart quickstart.cc) +target_compile_features(quickstart PRIVATE cxx_std_14) +target_link_libraries(quickstart PRIVATE google-cloud-cpp::pubsub + google-cloud-cpp::opentelemetry) diff --git a/pubsub-open-telemetry/README.md b/pubsub-open-telemetry/README.md new file mode 100644 index 0000000..5a2ee5b --- /dev/null +++ b/pubsub-open-telemetry/README.md @@ -0,0 +1,158 @@ +# Enabling Open Telemetry for the Pub/Sub library with Cloud Trace + +## Background + +In v2.16, we GA'd [OpenTelemetry tracing](https://github.com/googleapis/google-cloud-cpp/releases/tag/v2.16.0). This provides basic instrumentation for all the google-cloud-cpp libraries. + +In v2.19 release[^1], we added instrumentation for the Google Cloud Pub/Sub C++ library on the Publish side. This example provides a basic tracing application that exports spans to Cloud Trace. + +[^1]: The [telemetry data](https://github.com/googleapis/google-cloud-cpp/blob/main/doc/public-api.md#telemetry-data) emitted by the google-cloud-cpp library does not follow any versioning guarantees and is subject to change without notice in later versions. + +## Overview + +The quickstart installs a Cloud Trace exporter. The application creates a Pub/Sub client with tracing enabled that publishes 5 messages and sends the collected traces to Cloud Trace. + +### Example traces + +To find the traces, navigate to the Cloud Trace UI. + +![Screenshot of the Cloud Trace UI after running this quickstart.](assets/quickstart.png) + +For an overview of the Cloud Trace UI, see: [View traces overview]. + +## Prerequisites + +### 1. Create a project in the Google Cloud Platform Console + +If you haven't already created a project, create one now. + +Projects enable you to manage all Google Cloud Platform resources for your app, including deployment, access control, billing, and services. + +1. Open the [Cloud Platform Console](https://console.cloud.google.com/). +2. In the drop-down menu at the top, select Create a project. +3. Give your project a name. +4. Make a note of the project ID, which might be different from the project name. The project ID is used in commands and in configurations. + +### 2. Enable billing for your project +If you haven't already enabled billing for your +project, [enable billing now](https://console.cloud.google.com/project/_/settings). Enabling billing allows the +application to consume billable resources such as Pub/Sub API calls. + +See [Cloud Platform Console Help](https://support.google.com/cloud/answer/6288653) for more information about billing +settings. + +### 3. Enable APIs for your project +[Click here](https://console.cloud.google.com/flows/enableapi?apiid=speech&showconfirmation=true) to visit Cloud +Platform Console and enable the Pub/Sub and Trace API via the UI. + +Or use the CLI: + +``` +gcloud services enable trace.googleapis.com +gcloud services enable pubsub.googleapis.com +``` + +### 5. Create the Cloud Pub/Sub topic + +```sh +export=GOOGLE_CLOUD_PROJECT= +export=GOOGLE_CLOUD_TOPIC= +gcloud pubsub topics create "--project=${GOOGLE_CLOUD_PROJECT}" ${GOOGLE_CLOUD_TOPIC} +``` + +## Build and run using CMake and Vcpkg +### 1. Install vcpkg +This project uses [`vcpkg`](https://github.com/microsoft/vcpkg) for dependency management. Clone the vcpkg repository +to your preferred location. In these instructions we use`$HOME`: +```shell +git clone -C $HOME https://github.com/microsoft/vcpkg.git +cd $HOME/vcpkg +./vcpkg install google-cloud-cpp +``` + +### 2. Download or clone this repo + +```shell +git clone https://github.com/GoogleCloudPlatform/cpp-samples +``` + +### 3. Compile these examples + +Use the `vcpkg` toolchain file to download and compile dependencies. This file would be in the directory you +cloned `vcpkg` into, `$HOME/vcpkg` if you are following the instructions to the letter. Note that building all the +dependencies can take up to an hour, depending on the performance of your workstation. These dependencies are cached, +so a second build should be substantially faster. +```sh +cd cpp-samples/pubsub-open-telemetry +cmake -S . -B .build -DCMAKE_TOOLCHAIN_FILE=$HOME/vcpkg/scripts/buildsystems/vcpkg.cmake -G Ninja +cmake --build .build +``` + +### 4. Run the examples + +```shell +.build/quickstart [project-name] [topic-id] +``` + +## Build and run using Bazel + +### 1. Download or clone this repo + +```shell +git clone https://github.com/GoogleCloudPlatform/cpp-samples +``` + +### 2. Compile these examples + +```shell +cd cpp-samples/pubsub-open-telemetry +bazel build //:quickstart +``` + +### 3. Run these examples + +```shell + bazel run //:quickstart [project-name] [topic-id] +``` + +#### Run with a local version of google-cloud-cpp + +```shell +bazel run //:quickstart --override_repository=google_cloud_cpp=$HOME/your-path-to-the-repo/google-cloud-cpp -- [project-name] [topic-id] +``` + +## Cleanup + +```shell +gcloud pubsub topics delete "--project=${GOOGLE_CLOUD_PROJECT}" ${GOOGLE_CLOUD_TOPIC} +``` + +## Platform Specific Notes + +### macOS + +gRPC [requires][grpc-roots-pem-bug] an environment variable to configure the +trust store for SSL certificates, you can download and configure this using: + +```bash +curl -Lo roots.pem https://pki.google.com/roots.pem +export GRPC_DEFAULT_SSL_ROOTS_FILE_PATH="$PWD/roots.pem" +``` + +### Windows + +gRPC [requires][grpc-roots-pem-bug] an environment variable to configure the +trust store for SSL certificates, you can download and configure this using: + +```console +@powershell -NoProfile -ExecutionPolicy unrestricted -Command ^ + (new-object System.Net.WebClient).Downloadfile( ^ + 'https://pki.google.com/roots.pem', 'roots.pem') +set GRPC_DEFAULT_SSL_ROOTS_FILE_PATH=%cd%\roots.pem +``` + +[grpc-roots-pem-bug]: https://github.com/grpc/grpc/issues/16571 +[choco-cmake-link]: https://chocolatey.org/packages/cmake +[homebrew-cmake-link]: https://formulae.brew.sh/formula/cmake +[cmake-download-link]: https://cmake.org/download/ +[view traces overview]: https://cloud.google.com/trace/docs/trace-overview \ No newline at end of file diff --git a/pubsub-open-telemetry/WORKSPACE.bazel b/pubsub-open-telemetry/WORKSPACE.bazel new file mode 100644 index 0000000..0dfa4ba --- /dev/null +++ b/pubsub-open-telemetry/WORKSPACE.bazel @@ -0,0 +1,37 @@ +# Copyright 2023 Google LLC +# +# 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 +# +# https://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. + +workspace(name = "pubsub-open-telemetery") + +# Google Cloud Cpp +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +http_archive( + name = "google_cloud_cpp", + sha256 = "7ca7f583b60d2aa1274411fed3b9fb3887119b2e84244bb3fc69ea1db819e4e5", + strip_prefix = "google-cloud-cpp-2.16.0", + url = "https://github.com/googleapis/google-cloud-cpp/archive/v2.16.0.tar.gz", +) + +load("@google_cloud_cpp//bazel:google_cloud_cpp_deps.bzl", "google_cloud_cpp_deps") +google_cloud_cpp_deps() +load("@com_google_googleapis//:repository_rules.bzl", "switched_rules_by_language") +switched_rules_by_language( + name = "com_google_googleapis_imports", + cc = True, + grpc = True, +) +load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps") +grpc_deps() +load("@com_github_grpc_grpc//bazel:grpc_extra_deps.bzl", "grpc_extra_deps") +grpc_extra_deps() diff --git a/pubsub-open-telemetry/assets/quickstart.png b/pubsub-open-telemetry/assets/quickstart.png new file mode 100644 index 0000000..ef058d4 Binary files /dev/null and b/pubsub-open-telemetry/assets/quickstart.png differ diff --git a/pubsub-open-telemetry/quickstart.cc b/pubsub-open-telemetry/quickstart.cc new file mode 100644 index 0000000..430f53d --- /dev/null +++ b/pubsub-open-telemetry/quickstart.cc @@ -0,0 +1,79 @@ +// Copyright 2023 Google LLC +// +// 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 +// +// https://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. + +#include "google/cloud/opentelemetry/configure_basic_tracing.h" +#include "google/cloud/opentelemetry_options.h" +#include "google/cloud/pubsub/publisher.h" +#include "google/cloud/status.h" +#include +#include +#include +#include + +// Create a few namespace aliases to make the code easier to read. +namespace gc = ::google::cloud; +namespace pubsub = gc::pubsub; +namespace otel = gc::otel; + +int main(int argc, char* argv[]) try { + if (argc != 3) { + std::cerr << "Usage: " << argv[0] << " \n"; + return 1; + } + std::string const project_id = argv[1]; + std::string const topic_id = argv[2]; + auto project = gc::Project(project_id); + + //! [START pubsub_publish_otel_tracing] + // This example uses a simple wrapper to export (upload) OTel tracing data + // to Google Cloud Trace. More complex applications may use different + // authentication, or configure their own OTel exporter. + auto configuration = otel::ConfigureBasicTracing(project); + + auto publisher = pubsub::Publisher(pubsub::MakePublisherConnection( + pubsub::Topic(project_id, topic_id), + // Configure this publisher to enable OTel tracing. Some applications may + // chose to disable tracing in some publishers or to dynamically enable + // this option based on their own configuration. + gc::Options{}.set(true))); + + // After this point, use the Cloud Pub/Sub C++ client library as usual. + // In this example, we will send a few messages and configure a callback + // action for each one. + auto publisher = pubsub::Publisher(pubsub::MakePublisherConnection( + pubsub::Topic(project_id, topic_id), + gc::Options{}.set(true))); + + std::vector> ids; + for (int i = 0; i < 5; i++) { + auto id = publisher.Publish(pubsub::MessageBuilder().SetData("Hi!").Build()) + .then([](gc::future> f) { + auto id = f.get(); + if (!id) { + std::cout << "Error in publish: " << id.status() << "\n"; + return; + } + std::cout << "Sent message with id: (" << *id << ")\n"; + }); + ids.push_back(std::move(id)); + } + // Block until the messages are actually sent. + for (auto& id : ids) id.get(); + //! [END pubsub_publish_otel_tracing] + + return 0; +} catch (google::cloud::Status const& status) { + std::cerr << "google::cloud::Status thrown: " << status << "\n"; + return 1; +} diff --git a/pubsub-open-telemetry/vcpkg.json b/pubsub-open-telemetry/vcpkg.json new file mode 100644 index 0000000..a3a2a21 --- /dev/null +++ b/pubsub-open-telemetry/vcpkg.json @@ -0,0 +1,15 @@ +{ + "name": "gcp-cpp-samples-pubsub-open-telemetry-publisher", + "version-string": "unversioned", + "homepage": "https://github.com/GoogleCloudPlatform/cpp-samples/", + "description": "An example using Open Telemetry and the Pub/Sub library", + "dependencies": [ + { + "name": "google-cloud-cpp", + "features": [ + "pubsub", + "opentelemetry" + ] + } + ] +}