155 lines
3.8 KiB
C++
155 lines
3.8 KiB
C++
// Copyright The OpenTelemetry Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
// Include common Trace Provider API and processor
|
|
#include "opentelemetry/sdk/trace/simple_processor.h"
|
|
#include "opentelemetry/sdk/trace/tracer_provider.h"
|
|
#include "opentelemetry/trace/provider.h"
|
|
|
|
#include "opentelemetry/exporters/etw/etw_tracer_exporter.h"
|
|
|
|
#include <iostream>
|
|
#include <thread>
|
|
|
|
#include <cstdio>
|
|
#ifndef LOG_DEBUG
|
|
# include <mutex>
|
|
|
|
/**
|
|
* @brief Thread-safe logger routine.
|
|
* @param format
|
|
* @param args
|
|
* @return
|
|
*/
|
|
static inline int log_vprintf(const char *format, va_list args)
|
|
{
|
|
static std::mutex cout_mutex;
|
|
std::lock_guard<std::mutex> lk(cout_mutex);
|
|
return vprintf(format, args);
|
|
};
|
|
|
|
/**
|
|
* @brief Thread-safe logger routine.
|
|
* @param format
|
|
* @param
|
|
* @return
|
|
*/
|
|
static inline int log_printf(const char *format, ...)
|
|
{
|
|
int result;
|
|
va_list ap;
|
|
va_start(ap, format);
|
|
result = log_vprintf(format, ap);
|
|
va_end(ap);
|
|
return result;
|
|
};
|
|
|
|
// Debug macros
|
|
# define LOG_DEBUG(fmt_, ...) log_printf(" " fmt_ "\n", ##__VA_ARGS__)
|
|
# define LOG_TRACE(fmt_, ...) log_printf(" " fmt_ "\n", ##__VA_ARGS__)
|
|
# define LOG_INFO(fmt_, ...) log_printf(" " fmt_ "\n", ##__VA_ARGS__)
|
|
# define LOG_WARN(fmt_, ...) log_printf(" " fmt_ "\n", ##__VA_ARGS__)
|
|
# define LOG_ERROR(fmt_, ...) log_printf(" " fmt_ "\n", ##__VA_ARGS__)
|
|
#endif
|
|
|
|
using namespace OPENTELEMETRY_NAMESPACE;
|
|
|
|
using namespace opentelemetry::exporter::etw;
|
|
|
|
// Specify destination ETW Provider Name or GUID.
|
|
//
|
|
// In Visual Studio:
|
|
// - View -> Other Windows -> Diagnostic Events...
|
|
// - Click Configure (gear on top).
|
|
// - Specify "OpenTelemetry-ETW-TLD" in the list of providers.
|
|
//
|
|
// Event view shows event flow in realtime.
|
|
const char *kGlobalProviderName = "OpenTelemetry-ETW-TLD";
|
|
|
|
std::string providerName = kGlobalProviderName;
|
|
|
|
// One provider can be used to associate with different destinations.
|
|
exporter::etw::TracerProvider provider;
|
|
|
|
// Code below is generic and may be reused with any other TracerProvider.
|
|
// In ETW provider case - instrumentation name must match destination
|
|
// ETW provider name.
|
|
nostd::shared_ptr<trace::Tracer> tracer = provider.GetTracer(providerName, "1.0");
|
|
|
|
// Obtain numeric thread id
|
|
static inline uint64_t gettid()
|
|
{
|
|
std::stringstream ss;
|
|
ss << std::this_thread::get_id();
|
|
uint64_t id = std::stoull(ss.str());
|
|
return id;
|
|
}
|
|
|
|
// bop gets called by beep.
|
|
void bop()
|
|
{
|
|
LOG_TRACE("bop worker tid=%u", gettid());
|
|
auto span = tracer->StartSpan("bop");
|
|
span->AddEvent("BopEvent", {{"tid", gettid()}});
|
|
span->SetAttribute("attrib", 2);
|
|
span->End();
|
|
}
|
|
|
|
// beep gets called in its own thread.
|
|
// It is running in a thread pool, invoked via lambda by dispatcher.
|
|
void beep()
|
|
{
|
|
LOG_TRACE("beep worker tid=%u", gettid());
|
|
auto span = tracer->StartSpan("beep");
|
|
span->AddEvent("BeepEvent", {{"tid", gettid()}});
|
|
span->SetAttribute("attrib", 1);
|
|
{
|
|
auto bopScope = tracer->WithActiveSpan(span);
|
|
bop();
|
|
}
|
|
span->End();
|
|
}
|
|
|
|
// Max number of threads to spawn
|
|
constexpr int kMaxThreads = 10;
|
|
|
|
int main(int /*arc*/, char ** /*argv*/)
|
|
{
|
|
std::thread pool[kMaxThreads];
|
|
|
|
// Main dispatcher span: parent of all child thread spans.
|
|
auto mainSpan = tracer->StartSpan("beep_bop");
|
|
mainSpan->SetAttribute("attrib", 0);
|
|
|
|
// Start several threads to perform beep-bop actions.
|
|
LOG_TRACE("beep-boop dispatcher tid=%u", gettid());
|
|
for (auto i = 0; i < kMaxThreads; i++)
|
|
{
|
|
pool[i] = std::thread([&]() {
|
|
// This code runs in its own worker thread.
|
|
auto beepScope = tracer->WithActiveSpan(mainSpan);
|
|
// call beep -> bop
|
|
beep();
|
|
});
|
|
};
|
|
|
|
// Join all worker threads in the pool
|
|
for (auto &th : pool)
|
|
{
|
|
try
|
|
{
|
|
if (th.joinable())
|
|
th.join();
|
|
}
|
|
catch (...)
|
|
{
|
|
// thread might have been gracefully terminated already
|
|
}
|
|
}
|
|
|
|
// End span
|
|
mainSpan->End();
|
|
|
|
return 0;
|
|
}
|