// Copyright (C) 2019 The Android Open Source Project // // 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. // // This file is automatically generated by gen_amalgamated. Do not edit. // gen_amalgamated begin header: include/perfetto/tracing.h // gen_amalgamated begin header: include/perfetto/tracing/buffer_exhausted_policy.h /* * Copyright (C) 2019 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_TRACING_BUFFER_EXHAUSTED_POLICY_H_ #define INCLUDE_PERFETTO_TRACING_BUFFER_EXHAUSTED_POLICY_H_ namespace perfetto { // Determines how SharedMemoryArbiterImpl::GetNewChunk() behaves when no free // chunks are available. enum class BufferExhaustedPolicy { // SharedMemoryArbiterImpl::GetNewChunk() will stall if no free SMB chunk is // available and wait for the tracing service to free one. Note that this // requires that messages the arbiter sends to the tracing service (from any // TraceWriter thread) will be received by it, even if all TraceWriter threads // are stalled. kStall, // SharedMemoryArbiterImpl::GetNewChunk() will return an invalid chunk if no // free SMB chunk is available. In this case, the TraceWriter will fall back // to a garbage chunk and drop written data until acquiring a future chunk // succeeds again. kDrop, // TODO(eseckler): Switch to kDrop by default and change the Android code to // explicitly request kStall instead. kDefault = kStall }; } // namespace perfetto #endif // INCLUDE_PERFETTO_TRACING_BUFFER_EXHAUSTED_POLICY_H_ // gen_amalgamated begin header: include/perfetto/tracing/console_interceptor.h // gen_amalgamated begin header: include/perfetto/base/compiler.h // gen_amalgamated begin header: include/perfetto/base/build_config.h // gen_amalgamated begin header: gen/build_config/perfetto_build_flags.h /* * Copyright (C) 2019 The Android Open Source Project * * 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. */ // Generated by write_buildflag_header.py // fix_include_guards: off #ifndef GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_ #define GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_ // clang-format off #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ANDROID_BUILD() (0) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_CHROMIUM_BUILD() (0) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_STANDALONE_BUILD() (0) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_START_DAEMONS() (1) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_IPC() (1) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_WATCHDOG() (0) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPONENT_BUILD() (0) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DLOG_ON() (0) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DLOG_OFF() (0) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_VERBOSE_LOGS() (1) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_VERSION_GEN() (1) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_PERCENTILE() (0) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_LINENOISE() (0) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_HTTPD() (0) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON() (1) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_LOCAL_SYMBOLIZER() (0) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ZLIB() (1) // clang-format on #endif // GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_ /* * Copyright (C) 2017 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_BASE_BUILD_CONFIG_H_ #define INCLUDE_PERFETTO_BASE_BUILD_CONFIG_H_ // Allows to define build flags that give a compiler error if the header that // defined the flag is not included, instead of silently ignoring the #if block. #define PERFETTO_BUILDFLAG_CAT_INDIRECT(a, b) a##b #define PERFETTO_BUILDFLAG_CAT(a, b) PERFETTO_BUILDFLAG_CAT_INDIRECT(a, b) #define PERFETTO_BUILDFLAG(flag) \ (PERFETTO_BUILDFLAG_CAT(PERFETTO_BUILDFLAG_DEFINE_, flag)()) #if defined(__ANDROID__) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 1 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0 #elif defined(__APPLE__) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 1 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0 // Include TARGET_OS_IPHONE when on __APPLE__ systems. #include #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 1 #else #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 1 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0 #endif #elif defined(__linux__) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 1 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0 #elif defined(_WIN32) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 1 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0 #elif defined(__EMSCRIPTEN__) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 1 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0 #elif defined(__Fuchsia__) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 1 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0 #elif defined(__native_client__) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_APPLE() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MAC() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 1 #else #error OS not supported (see build_config.h) #endif #if defined(__clang__) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_CLANG() 1 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_GCC() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_MSVC() 0 #elif defined(__GNUC__) // Careful: Clang also defines this! #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_CLANG() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_GCC() 1 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_MSVC() 0 #elif defined(_MSC_VER) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_CLANG() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_GCC() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_MSVC() 1 #else #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_CLANG() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_GCC() 0 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_MSVC() 0 #endif #if defined(PERFETTO_BUILD_WITH_ANDROID_USERDEBUG) #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ANDROID_USERDEBUG_BUILD() 1 #else #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ANDROID_USERDEBUG_BUILD() 0 #endif // perfetto_build_flags.h contains the tweakable build flags defined via GN. // - In GN builds (e.g., standalone, chromium, v8) this file is generated at // build time via the gen_rule //gn/gen_buildflags. // - In Android in-tree builds, this file is generated by tools/gen_android_bp // and checked in into include/perfetto/base/build_configs/android_tree/. The // default cflags add this path to the default include path. // - Similarly, in bazel builds, this file is generated by tools/gen_bazel and // checked in into include/perfetto/base/build_configs/bazel/. // - In amaglamated builds, this file is generated by tools/gen_amalgamated and // added to the amalgamated headers. // gen_amalgamated expanded: #include "perfetto_build_flags.h" // no-include-violation-check #endif // INCLUDE_PERFETTO_BASE_BUILD_CONFIG_H_ /* * Copyright (C) 2019 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_BASE_COMPILER_H_ #define INCLUDE_PERFETTO_BASE_COMPILER_H_ #include #include // gen_amalgamated expanded: #include "perfetto/base/build_config.h" // __has_attribute is supported only by clang and recent versions of GCC. // Add a layer to wrap the __has_attribute macro. #if defined(__has_attribute) #define PERFETTO_HAS_ATTRIBUTE(x) __has_attribute(x) #else #define PERFETTO_HAS_ATTRIBUTE(x) 0 #endif #if defined(__GNUC__) || defined(__clang__) #define PERFETTO_LIKELY(_x) __builtin_expect(!!(_x), 1) #define PERFETTO_UNLIKELY(_x) __builtin_expect(!!(_x), 0) #else #define PERFETTO_LIKELY(_x) (_x) #define PERFETTO_UNLIKELY(_x) (_x) #endif #if defined(__GNUC__) || defined(__clang__) #define PERFETTO_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) #else #define PERFETTO_WARN_UNUSED_RESULT #endif #if defined(__clang__) #define PERFETTO_ALWAYS_INLINE __attribute__((__always_inline__)) #define PERFETTO_NO_INLINE __attribute__((__noinline__)) #else // GCC is too pedantic and often fails with the error: // "always_inline function might not be inlinable" #define PERFETTO_ALWAYS_INLINE #define PERFETTO_NO_INLINE #endif #if defined(__GNUC__) || defined(__clang__) #define PERFETTO_NORETURN __attribute__((__noreturn__)) #else #define PERFETTO_NORETURN __declspec(noreturn) #endif #if defined(__GNUC__) || defined(__clang__) #define PERFETTO_DEBUG_FUNCTION_IDENTIFIER() __PRETTY_FUNCTION__ #elif defined(_MSC_VER) #define PERFETTO_DEBUG_FUNCTION_IDENTIFIER() __FUNCSIG__ #else #define PERFETTO_DEBUG_FUNCTION_IDENTIFIER() \ static_assert(false, "Not implemented for this compiler") #endif #if defined(__GNUC__) || defined(__clang__) #define PERFETTO_PRINTF_FORMAT(x, y) \ __attribute__((__format__(__printf__, x, y))) #else #define PERFETTO_PRINTF_FORMAT(x, y) #endif #if PERFETTO_BUILDFLAG(PERFETTO_OS_IOS) // TODO(b/158814068): For iOS builds, thread_local is only supported since iOS // 8. We'd have to use pthread for thread local data instead here. For now, just // define it to nothing since we don't support running perfetto or the client // lib on iOS right now. #define PERFETTO_THREAD_LOCAL #else #define PERFETTO_THREAD_LOCAL thread_local #endif #if defined(__GNUC__) || defined(__clang__) #define PERFETTO_POPCOUNT(x) __builtin_popcountll(x) #else #include #define PERFETTO_POPCOUNT(x) __popcnt64(x) #endif #if defined(__clang__) #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) extern "C" void __asan_poison_memory_region(void const volatile*, size_t); extern "C" void __asan_unpoison_memory_region(void const volatile*, size_t); #define PERFETTO_ASAN_POISON(a, s) __asan_poison_memory_region((a), (s)) #define PERFETTO_ASAN_UNPOISON(a, s) __asan_unpoison_memory_region((a), (s)) #else #define PERFETTO_ASAN_POISON(addr, size) #define PERFETTO_ASAN_UNPOISON(addr, size) #endif // __has_feature(address_sanitizer) #else #define PERFETTO_ASAN_POISON(addr, size) #define PERFETTO_ASAN_UNPOISON(addr, size) #endif // __clang__ #if defined(__GNUC__) || defined(__clang__) #define PERFETTO_IS_LITTLE_ENDIAN() __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #else // Assume all MSVC targets are little endian. #define PERFETTO_IS_LITTLE_ENDIAN() 1 #endif // This is used for exporting xxxMain() symbols (e.g., PerfettoCmdMain, // ProbesMain) from libperfetto.so when the GN arg monolithic_binaries = false. #if defined(__GNUC__) || defined(__clang__) #define PERFETTO_EXPORT_ENTRYPOINT __attribute__((visibility("default"))) #else // TODO(primiano): on Windows this should be a pair of dllexport/dllimport. But // that requires a -DXXX_IMPLEMENTATION depending on whether we are on the // impl-site or call-site. Right now it's not worth the trouble as we // force-export the xxxMain() symbols only on Android, where we pack all the // code for N binaries into one .so to save binary size. On Windows we support // only monolithic binaries, as they are easier to deal with. #define PERFETTO_EXPORT_ENTRYPOINT #endif // Disables thread safety analysis for functions where the compiler can't // accurate figure out which locks are being held. #if defined(__clang__) #define PERFETTO_NO_THREAD_SAFETY_ANALYSIS \ __attribute__((no_thread_safety_analysis)) #else #define PERFETTO_NO_THREAD_SAFETY_ANALYSIS #endif // Avoid calling the exit-time destructor on an object with static lifetime. #if PERFETTO_HAS_ATTRIBUTE(no_destroy) #define PERFETTO_HAS_NO_DESTROY() 1 #define PERFETTO_NO_DESTROY __attribute__((no_destroy)) #else #define PERFETTO_HAS_NO_DESTROY() 0 #define PERFETTO_NO_DESTROY #endif namespace perfetto { namespace base { template inline void ignore_result(const T&...) {} } // namespace base } // namespace perfetto #endif // INCLUDE_PERFETTO_BASE_COMPILER_H_ // gen_amalgamated begin header: include/perfetto/base/logging.h // gen_amalgamated begin header: include/perfetto/base/export.h /* * Copyright (C) 2018 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_BASE_EXPORT_H_ #define INCLUDE_PERFETTO_BASE_EXPORT_H_ // gen_amalgamated expanded: #include "perfetto/base/build_config.h" #if PERFETTO_BUILDFLAG(PERFETTO_COMPONENT_BUILD) #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) #if defined(PERFETTO_IMPLEMENTATION) #define PERFETTO_EXPORT __declspec(dllexport) #else #define PERFETTO_EXPORT __declspec(dllimport) #endif #else // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) #if defined(PERFETTO_IMPLEMENTATION) #define PERFETTO_EXPORT __attribute__((visibility("default"))) #else #define PERFETTO_EXPORT #endif #endif // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) #else // !PERFETTO_BUILDFLAG(PERFETTO_COMPONENT_BUILD) #define PERFETTO_EXPORT #endif // PERFETTO_BUILDFLAG(PERFETTO_COMPONENT_BUILD) #endif // INCLUDE_PERFETTO_BASE_EXPORT_H_ /* * Copyright (C) 2017 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_BASE_LOGGING_H_ #define INCLUDE_PERFETTO_BASE_LOGGING_H_ #include #include // For strerror. // gen_amalgamated expanded: #include "perfetto/base/build_config.h" // gen_amalgamated expanded: #include "perfetto/base/compiler.h" // gen_amalgamated expanded: #include "perfetto/base/export.h" #if defined(__GNUC__) || defined(__clang__) // Ignore GCC warning about a missing argument for a variadic macro parameter. #pragma GCC system_header #endif // TODO(primiano): move this to base/build_config.h, turn into // PERFETTO_BUILDFLAG(DCHECK_IS_ON) and update call sites to use that instead. #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) #define PERFETTO_DCHECK_IS_ON() 0 #else #define PERFETTO_DCHECK_IS_ON() 1 #endif #if PERFETTO_BUILDFLAG(PERFETTO_FORCE_DLOG_ON) #define PERFETTO_DLOG_IS_ON() 1 #elif PERFETTO_BUILDFLAG(PERFETTO_FORCE_DLOG_OFF) #define PERFETTO_DLOG_IS_ON() 0 #else #define PERFETTO_DLOG_IS_ON() PERFETTO_DCHECK_IS_ON() #endif #if defined(PERFETTO_ANDROID_ASYNC_SAFE_LOG) #if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \ !PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD) #error "Async-safe logging is limited to Android tree builds" #endif // For binaries which need a very lightweight logging implementation. // Note that this header is incompatible with android/log.h. #include #elif PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) // Normal android logging. #include #endif namespace perfetto { namespace base { // Constexpr functions to extract basename(__FILE__), e.g.: ../foo/f.c -> f.c . constexpr const char* StrEnd(const char* s) { return *s ? StrEnd(s + 1) : s; } constexpr const char* BasenameRecursive(const char* s, const char* begin, const char* end) { return (*s == '/' && s < end) ? (s + 1) : ((s > begin) ? BasenameRecursive(s - 1, begin, end) : s); } constexpr const char* Basename(const char* str) { return BasenameRecursive(StrEnd(str), str, StrEnd(str)); } enum LogLev { kLogDebug = 0, kLogInfo, kLogImportant, kLogError }; struct LogMessageCallbackArgs { LogLev level; int line; const char* filename; const char* message; }; using LogMessageCallback = void (*)(LogMessageCallbackArgs); // This is not thread safe and must be called before using tracing from other // threads. PERFETTO_EXPORT void SetLogMessageCallback(LogMessageCallback callback); PERFETTO_EXPORT void LogMessage(LogLev, const char* fname, int line, const char* fmt, ...) PERFETTO_PRINTF_FORMAT(4, 5); #if defined(PERFETTO_ANDROID_ASYNC_SAFE_LOG) #define PERFETTO_XLOG(level, fmt, ...) \ do { \ async_safe_format_log((ANDROID_LOG_DEBUG + level), "perfetto", \ "%s:%d " fmt, ::perfetto::base::Basename(__FILE__), \ __LINE__, ##__VA_ARGS__); \ } while (0) #elif defined(PERFETTO_DISABLE_LOG) #define PERFETTO_XLOG(...) ::perfetto::base::ignore_result(__VA_ARGS__) #else #define PERFETTO_XLOG(level, fmt, ...) \ ::perfetto::base::LogMessage(level, ::perfetto::base::Basename(__FILE__), \ __LINE__, fmt, ##__VA_ARGS__) #endif #if defined(_MSC_VER) #define PERFETTO_IMMEDIATE_CRASH() \ do { \ __debugbreak(); \ __assume(0); \ } while (0) #else #define PERFETTO_IMMEDIATE_CRASH() \ do { \ __builtin_trap(); \ __builtin_unreachable(); \ } while (0) #endif #if PERFETTO_BUILDFLAG(PERFETTO_VERBOSE_LOGS) #define PERFETTO_LOG(fmt, ...) \ PERFETTO_XLOG(::perfetto::base::kLogInfo, fmt, ##__VA_ARGS__) #else // PERFETTO_BUILDFLAG(PERFETTO_VERBOSE_LOGS) #define PERFETTO_LOG(...) ::perfetto::base::ignore_result(__VA_ARGS__) #endif // PERFETTO_BUILDFLAG(PERFETTO_VERBOSE_LOGS) #define PERFETTO_ILOG(fmt, ...) \ PERFETTO_XLOG(::perfetto::base::kLogImportant, fmt, ##__VA_ARGS__) #define PERFETTO_ELOG(fmt, ...) \ PERFETTO_XLOG(::perfetto::base::kLogError, fmt, ##__VA_ARGS__) #define PERFETTO_FATAL(fmt, ...) \ do { \ PERFETTO_PLOG(fmt, ##__VA_ARGS__); \ PERFETTO_IMMEDIATE_CRASH(); \ } while (0) #if defined(__GNUC__) || defined(__clang__) #define PERFETTO_PLOG(x, ...) \ PERFETTO_ELOG(x " (errno: %d, %s)", ##__VA_ARGS__, errno, strerror(errno)) #else // MSVC expands __VA_ARGS__ in a different order. Give up, not worth it. #define PERFETTO_PLOG PERFETTO_ELOG #endif #define PERFETTO_CHECK(x) \ do { \ if (PERFETTO_UNLIKELY(!(x))) { \ PERFETTO_PLOG("%s", "PERFETTO_CHECK(" #x ")"); \ PERFETTO_IMMEDIATE_CRASH(); \ } \ } while (0) #if PERFETTO_DLOG_IS_ON() #define PERFETTO_DLOG(fmt, ...) \ PERFETTO_XLOG(::perfetto::base::kLogDebug, fmt, ##__VA_ARGS__) #if defined(__GNUC__) || defined(__clang__) #define PERFETTO_DPLOG(x, ...) \ PERFETTO_DLOG(x " (errno: %d, %s)", ##__VA_ARGS__, errno, strerror(errno)) #else // MSVC expands __VA_ARGS__ in a different order. Give up, not worth it. #define PERFETTO_DPLOG PERFETTO_DLOG #endif #else // PERFETTO_DLOG_IS_ON() #define PERFETTO_DLOG(...) ::perfetto::base::ignore_result(__VA_ARGS__) #define PERFETTO_DPLOG(...) ::perfetto::base::ignore_result(__VA_ARGS__) #endif // PERFETTO_DLOG_IS_ON() #if PERFETTO_DCHECK_IS_ON() #define PERFETTO_DCHECK(x) PERFETTO_CHECK(x) #define PERFETTO_DFATAL(...) PERFETTO_FATAL(__VA_ARGS__) #define PERFETTO_DFATAL_OR_ELOG(...) PERFETTO_DFATAL(__VA_ARGS__) #else // PERFETTO_DCHECK_IS_ON() #define PERFETTO_DCHECK(x) \ do { \ } while (false && (x)) #define PERFETTO_DFATAL(...) ::perfetto::base::ignore_result(__VA_ARGS__) #define PERFETTO_DFATAL_OR_ELOG(...) PERFETTO_ELOG(__VA_ARGS__) #endif // PERFETTO_DCHECK_IS_ON() } // namespace base } // namespace perfetto #endif // INCLUDE_PERFETTO_BASE_LOGGING_H_ // gen_amalgamated begin header: include/perfetto/tracing/interceptor.h // gen_amalgamated begin header: include/perfetto/protozero/field.h // gen_amalgamated begin header: include/perfetto/protozero/contiguous_memory_range.h /* * Copyright (C) 2017 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_PROTOZERO_CONTIGUOUS_MEMORY_RANGE_H_ #define INCLUDE_PERFETTO_PROTOZERO_CONTIGUOUS_MEMORY_RANGE_H_ #include #include #include namespace protozero { // Keep this struct trivially constructible (no ctors, no default initializers). struct ContiguousMemoryRange { uint8_t* begin; uint8_t* end; // STL style: one byte past the end of the buffer. inline bool is_valid() const { return begin != nullptr; } inline void reset() { begin = nullptr; } inline size_t size() const { return static_cast(end - begin); } }; } // namespace protozero #endif // INCLUDE_PERFETTO_PROTOZERO_CONTIGUOUS_MEMORY_RANGE_H_ // gen_amalgamated begin header: include/perfetto/protozero/proto_utils.h /* * Copyright (C) 2017 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_PROTOZERO_PROTO_UTILS_H_ #define INCLUDE_PERFETTO_PROTOZERO_PROTO_UTILS_H_ #include #include #include // gen_amalgamated expanded: #include "perfetto/base/logging.h" namespace protozero { namespace proto_utils { // See https://developers.google.com/protocol-buffers/docs/encoding wire types. // This is a type encoded into the proto that provides just enough info to // find the length of the following value. enum class ProtoWireType : uint32_t { kVarInt = 0, kFixed64 = 1, kLengthDelimited = 2, kFixed32 = 5, }; // This is the type defined in the proto for each field. This information // is used to decide the translation strategy when writing the trace. enum class ProtoSchemaType { kUnknown = 0, kDouble, kFloat, kInt64, kUint64, kInt32, kFixed64, kFixed32, kBool, kString, kGroup, // Deprecated (proto2 only) kMessage, kBytes, kUint32, kEnum, kSfixed32, kSfixed64, kSint32, kSint64, }; inline const char* ProtoSchemaToString(ProtoSchemaType v) { switch (v) { case ProtoSchemaType::kUnknown: return "unknown"; case ProtoSchemaType::kDouble: return "double"; case ProtoSchemaType::kFloat: return "float"; case ProtoSchemaType::kInt64: return "int64"; case ProtoSchemaType::kUint64: return "uint64"; case ProtoSchemaType::kInt32: return "int32"; case ProtoSchemaType::kFixed64: return "fixed64"; case ProtoSchemaType::kFixed32: return "fixed32"; case ProtoSchemaType::kBool: return "bool"; case ProtoSchemaType::kString: return "string"; case ProtoSchemaType::kGroup: return "group"; case ProtoSchemaType::kMessage: return "message"; case ProtoSchemaType::kBytes: return "bytes"; case ProtoSchemaType::kUint32: return "uint32"; case ProtoSchemaType::kEnum: return "enum"; case ProtoSchemaType::kSfixed32: return "sfixed32"; case ProtoSchemaType::kSfixed64: return "sfixed64"; case ProtoSchemaType::kSint32: return "sint32"; case ProtoSchemaType::kSint64: return "sint64"; } // For gcc: PERFETTO_DCHECK(false); return ""; } // Maximum message size supported: 256 MiB (4 x 7-bit due to varint encoding). constexpr size_t kMessageLengthFieldSize = 4; constexpr size_t kMaxMessageLength = (1u << (kMessageLengthFieldSize * 7)) - 1; // Field tag is encoded as 32-bit varint (5 bytes at most). // Largest value of simple (not length-delimited) field is 64-bit varint // (10 bytes at most). 15 bytes buffer is enough to store a simple field. constexpr size_t kMaxTagEncodedSize = 5; constexpr size_t kMaxSimpleFieldEncodedSize = kMaxTagEncodedSize + 10; // Proto types: (int|uint|sint)(32|64), bool, enum. constexpr uint32_t MakeTagVarInt(uint32_t field_id) { return (field_id << 3) | static_cast(ProtoWireType::kVarInt); } // Proto types: fixed64, sfixed64, fixed32, sfixed32, double, float. template constexpr uint32_t MakeTagFixed(uint32_t field_id) { static_assert(sizeof(T) == 8 || sizeof(T) == 4, "Value must be 4 or 8 bytes"); return (field_id << 3) | static_cast((sizeof(T) == 8 ? ProtoWireType::kFixed64 : ProtoWireType::kFixed32)); } // Proto types: string, bytes, embedded messages. constexpr uint32_t MakeTagLengthDelimited(uint32_t field_id) { return (field_id << 3) | static_cast(ProtoWireType::kLengthDelimited); } // Proto types: sint64, sint32. template inline typename std::make_unsigned::type ZigZagEncode(T value) { using UnsignedType = typename std::make_unsigned::type; // Right-shift of negative values is implementation specific. // Assert the implementation does what we expect, which is that shifting any // positive value by sizeof(T) * 8 - 1 gives an all 0 bitmap, and a negative // value gives and all 1 bitmap. constexpr uint64_t kUnsignedZero = 0u; constexpr int64_t kNegativeOne = -1; constexpr int64_t kPositiveOne = 1; static_assert(static_cast(kNegativeOne >> 63) == ~kUnsignedZero, "implementation does not support assumed rightshift"); static_assert(static_cast(kPositiveOne >> 63) == kUnsignedZero, "implementation does not support assumed rightshift"); return (static_cast(value) << 1) ^ static_cast(value >> (sizeof(T) * 8 - 1)); } // Proto types: sint64, sint32. template inline typename std::make_signed::type ZigZagDecode(T value) { using UnsignedType = typename std::make_unsigned::type; using SignedType = typename std::make_signed::type; auto u_value = static_cast(value); auto mask = static_cast(-static_cast(u_value & 1)); return static_cast((u_value >> 1) ^ mask); } template inline uint8_t* WriteVarInt(T value, uint8_t* target) { // If value is <= 0 we must first sign extend to int64_t (see [1]). // Finally we always cast to an unsigned value to to avoid arithmetic // (sign expanding) shifts in the while loop. // [1]: "If you use int32 or int64 as the type for a negative number, the // resulting varint is always ten bytes long". // - developers.google.com/protocol-buffers/docs/encoding // So for each input type we do the following casts: // uintX_t -> uintX_t -> uintX_t // int8_t -> int64_t -> uint64_t // int16_t -> int64_t -> uint64_t // int32_t -> int64_t -> uint64_t // int64_t -> int64_t -> uint64_t using MaybeExtendedType = typename std::conditional::value, T, int64_t>::type; using UnsignedType = typename std::make_unsigned::type; MaybeExtendedType extended_value = static_cast(value); UnsignedType unsigned_value = static_cast(extended_value); while (unsigned_value >= 0x80) { *target++ = static_cast(unsigned_value) | 0x80; unsigned_value >>= 7; } *target = static_cast(unsigned_value); return target + 1; } // Writes a fixed-size redundant encoding of the given |value|. This is // used to backfill fixed-size reservations for the length field using a // non-canonical varint encoding (e.g. \x81\x80\x80\x00 instead of \x01). // See https://github.com/google/protobuf/issues/1530. // This is used mainly in two cases: // 1) At trace writing time, when starting a nested messages. The size of a // nested message is not known until all its field have been written. // |kMessageLengthFieldSize| bytes are reserved to encode the size field and // backfilled at the end. // 2) When rewriting a message at trace filtering time, in protozero/filtering. // At that point we know only the upper bound of the length (a filtered // message is <= the original one) and we backfill after the message has been // filtered. inline void WriteRedundantVarInt(uint32_t value, uint8_t* buf, size_t size = kMessageLengthFieldSize) { for (size_t i = 0; i < size; ++i) { const uint8_t msb = (i < size - 1) ? 0x80 : 0; buf[i] = static_cast(value) | msb; value >>= 7; } } template void StaticAssertSingleBytePreamble() { static_assert(field_id < 16, "Proto field id too big to fit in a single byte preamble"); } // Parses a VarInt from the encoded buffer [start, end). |end| is STL-style and // points one byte past the end of buffer. // The parsed int value is stored in the output arg |value|. Returns a pointer // to the next unconsumed byte (so start < retval <= end) or |start| if the // VarInt could not be fully parsed because there was not enough space in the // buffer. inline const uint8_t* ParseVarInt(const uint8_t* start, const uint8_t* end, uint64_t* out_value) { const uint8_t* pos = start; uint64_t value = 0; for (uint32_t shift = 0; pos < end && shift < 64u; shift += 7) { // Cache *pos into |cur_byte| to prevent that the compiler dereferences the // pointer twice (here and in the if() below) due to char* aliasing rules. uint8_t cur_byte = *pos++; value |= static_cast(cur_byte & 0x7f) << shift; if ((cur_byte & 0x80) == 0) { // In valid cases we get here. *out_value = value; return pos; } } *out_value = 0; return start; } enum class RepetitionType { kNotRepeated, kRepeatedPacked, kRepeatedNotPacked, }; // Provide a common base struct for all templated FieldMetadata types to allow // simple checks if a given type is a FieldMetadata or not. struct FieldMetadataBase { constexpr FieldMetadataBase() = default; }; template struct FieldMetadata : public FieldMetadataBase { constexpr FieldMetadata() = default; static constexpr int kFieldId = field_id; // Whether this field is repeated, packed (repeated [packed-true]) or not // (optional). static constexpr RepetitionType kRepetitionType = repetition_type; // Proto type of this field (e.g. int64, fixed32 or nested message). static constexpr ProtoSchemaType kProtoFieldType = proto_schema_type; // C++ type of this field (for nested messages - C++ protozero class). using cpp_field_type = CppFieldType; // Protozero message which this field belongs to. using message_type = MessageType; }; namespace internal { // Ideally we would create variables of FieldMetadata<...> type directly, // but before C++17's support for constexpr inline variables arrive, we have to // actually use pointers to inline functions instead to avoid having to define // symbols in *.pbzero.cc files. // // Note: protozero bindings will generate Message::kFieldName variable and which // can then be passed to TRACE_EVENT macro for inline writing of typed messages. // The fact that the former can be passed to the latter is a part of the stable // API, while the particular type is not and users should not rely on it. template using FieldMetadataHelper = T (*)(void); } // namespace internal } // namespace proto_utils } // namespace protozero #endif // INCLUDE_PERFETTO_PROTOZERO_PROTO_UTILS_H_ /* * Copyright (C) 2019 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_PROTOZERO_FIELD_H_ #define INCLUDE_PERFETTO_PROTOZERO_FIELD_H_ #include #include #include // gen_amalgamated expanded: #include "perfetto/base/logging.h" // gen_amalgamated expanded: #include "perfetto/protozero/contiguous_memory_range.h" // gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h" namespace protozero { struct ConstBytes { std::string ToStdString() const { return std::string(reinterpret_cast(data), size); } const uint8_t* data; size_t size; }; struct ConstChars { // Allow implicit conversion to perfetto's base::StringView without depending // on perfetto/base or viceversa. static constexpr bool kConvertibleToStringView = true; std::string ToStdString() const { return std::string(data, size); } const char* data; size_t size; }; // A protobuf field decoded by the protozero proto decoders. It exposes // convenience accessors with minimal debug checks. // This class is used both by the iterator-based ProtoDecoder and by the // one-shot TypedProtoDecoder. // If the field is not valid the accessors consistently return zero-integers or // null strings. class Field { public: bool valid() const { return id_ != 0; } uint16_t id() const { return id_; } explicit operator bool() const { return valid(); } proto_utils::ProtoWireType type() const { auto res = static_cast(type_); PERFETTO_DCHECK(res == proto_utils::ProtoWireType::kVarInt || res == proto_utils::ProtoWireType::kLengthDelimited || res == proto_utils::ProtoWireType::kFixed32 || res == proto_utils::ProtoWireType::kFixed64); return res; } bool as_bool() const { PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt); return static_cast(int_value_); } uint32_t as_uint32() const { PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt || type() == proto_utils::ProtoWireType::kFixed32); return static_cast(int_value_); } int32_t as_int32() const { PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt || type() == proto_utils::ProtoWireType::kFixed32); return static_cast(int_value_); } int32_t as_sint32() const { PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt); return proto_utils::ZigZagDecode(static_cast(int_value_)); } uint64_t as_uint64() const { PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt || type() == proto_utils::ProtoWireType::kFixed32 || type() == proto_utils::ProtoWireType::kFixed64); return int_value_; } int64_t as_int64() const { PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt || type() == proto_utils::ProtoWireType::kFixed32 || type() == proto_utils::ProtoWireType::kFixed64); return static_cast(int_value_); } int64_t as_sint64() const { PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt); return proto_utils::ZigZagDecode(static_cast(int_value_)); } float as_float() const { PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kFixed32); float res; uint32_t value32 = static_cast(int_value_); memcpy(&res, &value32, sizeof(res)); return res; } double as_double() const { PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kFixed64); double res; memcpy(&res, &int_value_, sizeof(res)); return res; } ConstChars as_string() const { PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kLengthDelimited); return ConstChars{reinterpret_cast(data()), size_}; } std::string as_std_string() const { return as_string().ToStdString(); } ConstBytes as_bytes() const { PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kLengthDelimited); return ConstBytes{data(), size_}; } const uint8_t* data() const { PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kLengthDelimited); return reinterpret_cast(int_value_); } size_t size() const { PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kLengthDelimited); return size_; } uint64_t raw_int_value() const { return int_value_; } void initialize(uint16_t id, uint8_t type, uint64_t int_value, uint32_t size) { id_ = id; type_ = type; int_value_ = int_value; size_ = size; } // For use with templates. This is used by RepeatedFieldIterator::operator*(). void get(bool* val) const { *val = as_bool(); } void get(uint32_t* val) const { *val = as_uint32(); } void get(int32_t* val) const { *val = as_int32(); } void get(uint64_t* val) const { *val = as_uint64(); } void get(int64_t* val) const { *val = as_int64(); } void get(float* val) const { *val = as_float(); } void get(double* val) const { *val = as_double(); } void get(std::string* val) const { *val = as_std_string(); } void get(ConstChars* val) const { *val = as_string(); } void get(ConstBytes* val) const { *val = as_bytes(); } void get_signed(int32_t* val) const { *val = as_sint32(); } void get_signed(int64_t* val) const { *val = as_sint64(); } // For enum types. template ::value, T>::type> void get(T* val) const { *val = static_cast(as_int32()); } // Serializes the field back into a proto-encoded byte stream and appends it // to |dst|. |dst| is resized accordingly. void SerializeAndAppendTo(std::string* dst) const; // Serializes the field back into a proto-encoded byte stream and appends it // to |dst|. |dst| is resized accordingly. void SerializeAndAppendTo(std::vector* dst) const; private: template void SerializeAndAppendToInternal(Container* dst) const; // Fields are deliberately not initialized to keep the class trivially // constructible. It makes a large perf difference for ProtoDecoder. uint64_t int_value_; // In kLengthDelimited this contains the data() addr. uint32_t size_; // Only valid when when type == kLengthDelimited. uint16_t id_; // Proto field ordinal. uint8_t type_; // proto_utils::ProtoWireType. }; // The Field struct is used in a lot of perf-sensitive contexts. static_assert(sizeof(Field) == 16, "Field struct too big"); } // namespace protozero #endif // INCLUDE_PERFETTO_PROTOZERO_FIELD_H_ // gen_amalgamated begin header: include/perfetto/tracing/core/forward_decls.h /* * Copyright (C) 2019 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_TRACING_CORE_FORWARD_DECLS_H_ #define INCLUDE_PERFETTO_TRACING_CORE_FORWARD_DECLS_H_ // Forward declares classes that are generated at build-time from protos. // First of all, why are we forward declaring at all? // 1. Chromium diverges from the Google style guide on this, because forward // declarations typically make build times faster, and that's a desirable // property for a large and complex codebase. // 2. Adding #include to build-time-generated headers from headers typically // creates subtle build errors that are hard to spot in GN. This is because // once a standard header (say foo.h) has an #include "protos/foo.gen.h", // the build target that depends on foo.h needs to depend on the genrule // that generates foo.gen.h. This is achievable using public_deps in GN but // is not testable / enforceable, hence too easy to get wrong. // Historically the classes below used to be generated from the corresponding // .proto(s) at CL *check-in* time (!= build time) in the ::perfetto namespace. // Nowadays we have code everywhere that assume the right class is // ::perfetto::TraceConfig or the like. Back then other headers could just // forward declared ::perfetto::TraceConfig. These days, the real class is // ::perfetto::protos::gen::TraceConfig and core/trace_config.h aliases that as // using ::perfetto::TraceConfig = ::perfetto::protos::gen::TraceConfig. // In C++ one cannot forward declare a type alias (but only the aliased type). // Hence this header, which should be used every time one wants to forward // declare classes like TraceConfig. // The overall plan is that, when one of the classes below is needed: // The .h file includes this file. // The .cc file includes perfetto/tracing/core/trace_config.h (or equiv). That // header will pull the full declaration from trace_config.gen.h and will also // setup the alias in the ::perfetto namespace. namespace perfetto { namespace protos { namespace gen { class ChromeConfig; class CommitDataRequest; class DataSourceConfig; class DataSourceDescriptor; class ObservableEvents; class TraceConfig; class TraceStats; class TracingServiceCapabilities; class TracingServiceState; } // namespace gen } // namespace protos using ChromeConfig = ::perfetto::protos::gen::ChromeConfig; using CommitDataRequest = ::perfetto::protos::gen::CommitDataRequest; using DataSourceConfig = ::perfetto::protos::gen::DataSourceConfig; using DataSourceDescriptor = ::perfetto::protos::gen::DataSourceDescriptor; using ObservableEvents = ::perfetto::protos::gen::ObservableEvents; using TraceConfig = ::perfetto::protos::gen::TraceConfig; using TraceStats = ::perfetto::protos::gen::TraceStats; using TracingServiceCapabilities = ::perfetto::protos::gen::TracingServiceCapabilities; using TracingServiceState = ::perfetto::protos::gen::TracingServiceState; } // namespace perfetto #endif // INCLUDE_PERFETTO_TRACING_CORE_FORWARD_DECLS_H_ // gen_amalgamated begin header: include/perfetto/tracing/internal/basic_types.h /* * Copyright (C) 2019 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_BASIC_TYPES_H_ #define INCLUDE_PERFETTO_TRACING_INTERNAL_BASIC_TYPES_H_ #include #include namespace perfetto { namespace internal { // A static_assert in tracing_muxer_impl.cc guarantees that this stays in sync // with the definition in tracing/core/basic_types.h using BufferId = uint16_t; // This is a direct index in the TracingMuxer::backends_ vector. // Backends are only added and never removed. using TracingBackendId = size_t; // Max numbers of data sources that can be registered in a process. constexpr size_t kMaxDataSources = 32; // Max instances for each data source type. This typically matches the // "max number of concurrent tracing sessions". However remember that a data // source can be instantiated more than once within one tracing session by // creating two entries for it in the trace config. constexpr size_t kMaxDataSourceInstances = 8; } // namespace internal } // namespace perfetto #endif // INCLUDE_PERFETTO_TRACING_INTERNAL_BASIC_TYPES_H_ // gen_amalgamated begin header: include/perfetto/tracing/internal/data_source_internal.h // gen_amalgamated begin header: include/perfetto/tracing/trace_writer_base.h // gen_amalgamated begin header: include/perfetto/protozero/message_handle.h // gen_amalgamated begin header: include/perfetto/protozero/message.h // gen_amalgamated begin header: include/perfetto/protozero/scattered_stream_writer.h /* * Copyright (C) 2017 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_PROTOZERO_SCATTERED_STREAM_WRITER_H_ #define INCLUDE_PERFETTO_PROTOZERO_SCATTERED_STREAM_WRITER_H_ #include #include #include #include // gen_amalgamated expanded: #include "perfetto/base/compiler.h" // gen_amalgamated expanded: #include "perfetto/base/export.h" // gen_amalgamated expanded: #include "perfetto/protozero/contiguous_memory_range.h" namespace protozero { // This class deals with the following problem: append-only proto messages want // to write a stream of bytes, without caring about the implementation of the // underlying buffer (which concretely will be either the trace ring buffer // or a heap-allocated buffer). The main deal is: proto messages don't know in // advance what their size will be. // Due to the tracing buffer being split into fixed-size chunks, on some // occasions, these writes need to be spread over two (or more) non-contiguous // chunks of memory. Similarly, when the buffer is backed by the heap, we want // to avoid realloc() calls, as they might cause a full copy of the contents // of the buffer. // The purpose of this class is to abstract away the non-contiguous write logic. // This class knows how to deal with writes as long as they fall in the same // ContiguousMemoryRange and defers the chunk-chaining logic to the Delegate. class PERFETTO_EXPORT ScatteredStreamWriter { public: class PERFETTO_EXPORT Delegate { public: virtual ~Delegate(); virtual ContiguousMemoryRange GetNewBuffer() = 0; }; explicit ScatteredStreamWriter(Delegate* delegate); ~ScatteredStreamWriter(); inline void WriteByte(uint8_t value) { if (write_ptr_ >= cur_range_.end) Extend(); *write_ptr_++ = value; } // Assumes that the caller checked that there is enough headroom. // TODO(primiano): perf optimization, this is a tracing hot path. The // compiler can make strong optimization on memcpy if the size arg is a // constexpr. Make a templated variant of this for fixed-size writes. // TODO(primiano): restrict / noalias might also help. inline void WriteBytesUnsafe(const uint8_t* src, size_t size) { uint8_t* const end = write_ptr_ + size; assert(end <= cur_range_.end); memcpy(write_ptr_, src, size); write_ptr_ = end; } inline void WriteBytes(const uint8_t* src, size_t size) { uint8_t* const end = write_ptr_ + size; if (PERFETTO_LIKELY(end <= cur_range_.end)) return WriteBytesUnsafe(src, size); WriteBytesSlowPath(src, size); } void WriteBytesSlowPath(const uint8_t* src, size_t size); // Reserves a fixed amount of bytes to be backfilled later. The reserved range // is guaranteed to be contiguous and not span across chunks. |size| has to be // <= than the size of a new buffer returned by the Delegate::GetNewBuffer(). uint8_t* ReserveBytes(size_t size); // Fast (but unsafe) version of the above. The caller must have previously // checked that there are at least |size| contiguous bytes available. // Returns only the start pointer of the reservation. uint8_t* ReserveBytesUnsafe(size_t size) { uint8_t* begin = write_ptr_; write_ptr_ += size; assert(write_ptr_ <= cur_range_.end); return begin; } // Resets the buffer boundaries and the write pointer to the given |range|. // Subsequent WriteByte(s) will write into |range|. void Reset(ContiguousMemoryRange range); // Number of contiguous free bytes in |cur_range_| that can be written without // requesting a new buffer. size_t bytes_available() const { return static_cast(cur_range_.end - write_ptr_); } uint8_t* write_ptr() const { return write_ptr_; } uint64_t written() const { return written_previously_ + static_cast(write_ptr_ - cur_range_.begin); } private: ScatteredStreamWriter(const ScatteredStreamWriter&) = delete; ScatteredStreamWriter& operator=(const ScatteredStreamWriter&) = delete; void Extend(); Delegate* const delegate_; ContiguousMemoryRange cur_range_; uint8_t* write_ptr_; uint64_t written_previously_ = 0; }; } // namespace protozero #endif // INCLUDE_PERFETTO_PROTOZERO_SCATTERED_STREAM_WRITER_H_ /* * Copyright (C) 2017 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_PROTOZERO_MESSAGE_H_ #define INCLUDE_PERFETTO_PROTOZERO_MESSAGE_H_ #include #include #include #include #include // gen_amalgamated expanded: #include "perfetto/base/export.h" // gen_amalgamated expanded: #include "perfetto/base/logging.h" // gen_amalgamated expanded: #include "perfetto/protozero/contiguous_memory_range.h" // gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h" // gen_amalgamated expanded: #include "perfetto/protozero/scattered_stream_writer.h" namespace perfetto { namespace shm_fuzz { class FakeProducer; } // namespace shm_fuzz } // namespace perfetto namespace protozero { class MessageArena; class MessageHandleBase; // Base class extended by the proto C++ stubs generated by the ProtoZero // compiler. This class provides the minimal runtime required to support // append-only operations and is designed for performance. None of the methods // require any dynamic memory allocation, unless more than 16 nested messages // are created via BeginNestedMessage() calls. class PERFETTO_EXPORT Message { public: friend class MessageHandleBase; // The ctor is deliberately a no-op to avoid forwarding args from all // subclasses. The real initialization is performed by Reset(). // Nested messages are allocated via placement new by MessageArena and // implictly destroyed when the RootMessage's arena goes away. This is // fine as long as all the fields are PODs, which is checked by the // static_assert()s in the Reset() method. Message() = default; // Clears up the state, allowing the message to be reused as a fresh one. void Reset(ScatteredStreamWriter*, MessageArena*); // Commits all the changes to the buffer (backfills the size field of this and // all nested messages) and seals the message. Returns the size of the message // (and all nested sub-messages), without taking into account any chunking. // Finalize is idempotent and can be called several times w/o side effects. uint32_t Finalize(); // Optional. If is_valid() == true, the corresponding memory region (its // length == proto_utils::kMessageLengthFieldSize) is backfilled with the size // of this message (minus |size_already_written| below). This is the mechanism // used by messages to backfill their corresponding size field in the parent // message. uint8_t* size_field() const { return size_field_; } void set_size_field(uint8_t* size_field) { size_field_ = size_field; } // This is to deal with case of backfilling the size of a root (non-nested) // message which is split into multiple chunks. Upon finalization only the // partial size that lies in the last chunk has to be backfilled. void inc_size_already_written(uint32_t sz) { size_already_written_ += sz; } Message* nested_message() { return nested_message_; } bool is_finalized() const { return finalized_; } #if PERFETTO_DCHECK_IS_ON() void set_handle(MessageHandleBase* handle) { handle_ = handle; } #endif // Proto types: uint64, uint32, int64, int32, bool, enum. template void AppendVarInt(uint32_t field_id, T value) { if (nested_message_) EndNestedMessage(); uint8_t buffer[proto_utils::kMaxSimpleFieldEncodedSize]; uint8_t* pos = buffer; pos = proto_utils::WriteVarInt(proto_utils::MakeTagVarInt(field_id), pos); // WriteVarInt encodes signed values in two's complement form. pos = proto_utils::WriteVarInt(value, pos); WriteToStream(buffer, pos); } // Proto types: sint64, sint32. template void AppendSignedVarInt(uint32_t field_id, T value) { AppendVarInt(field_id, proto_utils::ZigZagEncode(value)); } // Proto types: bool, enum (small). // Faster version of AppendVarInt for tiny numbers. void AppendTinyVarInt(uint32_t field_id, int32_t value) { PERFETTO_DCHECK(0 <= value && value < 0x80); if (nested_message_) EndNestedMessage(); uint8_t buffer[proto_utils::kMaxSimpleFieldEncodedSize]; uint8_t* pos = buffer; // MakeTagVarInt gets super optimized here for constexpr. pos = proto_utils::WriteVarInt(proto_utils::MakeTagVarInt(field_id), pos); *pos++ = static_cast(value); WriteToStream(buffer, pos); } // Proto types: fixed64, sfixed64, fixed32, sfixed32, double, float. template void AppendFixed(uint32_t field_id, T value) { if (nested_message_) EndNestedMessage(); uint8_t buffer[proto_utils::kMaxSimpleFieldEncodedSize]; uint8_t* pos = buffer; pos = proto_utils::WriteVarInt(proto_utils::MakeTagFixed(field_id), pos); memcpy(pos, &value, sizeof(T)); pos += sizeof(T); // TODO: Optimize memcpy performance, see http://crbug.com/624311 . WriteToStream(buffer, pos); } void AppendString(uint32_t field_id, const char* str); void AppendString(uint32_t field_id, const std::string& str) { AppendBytes(field_id, str.data(), str.size()); } void AppendBytes(uint32_t field_id, const void* value, size_t size); // Append raw bytes for a field, using the supplied |ranges| to // copy from |num_ranges| individual buffers. size_t AppendScatteredBytes(uint32_t field_id, ContiguousMemoryRange* ranges, size_t num_ranges); // Begins a nested message. The returned object is owned by the MessageArena // of the root message. The nested message ends either when Finalize() is // called or when any other Append* method is called in the parent class. // The template argument T is supposed to be a stub class auto generated from // a .proto, hence a subclass of Message. template T* BeginNestedMessage(uint32_t field_id) { // This is to prevent subclasses (which should be autogenerated, though), to // introduce extra state fields (which wouldn't be initialized by Reset()). static_assert(std::is_base_of::value, "T must be a subclass of Message"); static_assert(sizeof(T) == sizeof(Message), "Message subclasses cannot introduce extra state."); return static_cast(BeginNestedMessageInternal(field_id)); } // Gives read-only access to the underlying stream_writer. This is used only // by few internals to query the state of the underlying buffer. It is almost // always a bad idea to poke at the stream_writer() internals. const ScatteredStreamWriter* stream_writer() const { return stream_writer_; } // Appends some raw bytes to the message. The use-case for this is preserving // unknown fields in the decode -> re-encode path of xxx.gen.cc classes // generated by the cppgen_plugin.cc. // The caller needs to guarantee that the appended data is properly // proto-encoded and each field has a proto preamble. void AppendRawProtoBytes(const void* data, size_t size) { const uint8_t* src = reinterpret_cast(data); WriteToStream(src, src + size); } private: Message(const Message&) = delete; Message& operator=(const Message&) = delete; Message* BeginNestedMessageInternal(uint32_t field_id); // Called by Finalize and Append* methods. void EndNestedMessage(); void WriteToStream(const uint8_t* src_begin, const uint8_t* src_end) { PERFETTO_DCHECK(!finalized_); PERFETTO_DCHECK(src_begin <= src_end); const uint32_t size = static_cast(src_end - src_begin); stream_writer_->WriteBytes(src_begin, size); size_ += size; } // Only POD fields are allowed. This class's dtor is never called. // See the comment on the static_assert in the corresponding .cc file. // The stream writer interface used for the serialization. ScatteredStreamWriter* stream_writer_; // The storage used to allocate nested Message objects. // This is owned by RootMessage. MessageArena* arena_; // Pointer to the last child message created through BeginNestedMessage(), if // any, nullptr otherwise. There is no need to keep track of more than one // message per nesting level as the proto-zero API contract mandates that // nested fields can be filled only in a stacked fashion. In other words, // nested messages are finalized and sealed when any other field is set in the // parent message (or the parent message itself is finalized) and cannot be // accessed anymore afterwards. Message* nested_message_; // [optional] Pointer to a non-aligned pre-reserved var-int slot of // kMessageLengthFieldSize bytes. When set, the Finalize() method will write // the size of proto-encoded message in the pointed memory region. uint8_t* size_field_; // Keeps track of the size of the current message. uint32_t size_; // See comment for inc_size_already_written(). uint32_t size_already_written_; // When true, no more changes to the message are allowed. This is to DCHECK // attempts of writing to a message which has been Finalize()-d. bool finalized_; #if PERFETTO_DCHECK_IS_ON() // Current generation of message. Incremented on Reset. // Used to detect stale handles. uint32_t generation_; MessageHandleBase* handle_; #endif }; } // namespace protozero #endif // INCLUDE_PERFETTO_PROTOZERO_MESSAGE_H_ /* * Copyright (C) 2017 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_PROTOZERO_MESSAGE_HANDLE_H_ #define INCLUDE_PERFETTO_PROTOZERO_MESSAGE_HANDLE_H_ #include // gen_amalgamated expanded: #include "perfetto/base/export.h" // gen_amalgamated expanded: #include "perfetto/protozero/message.h" namespace protozero { class Message; // MessageHandle allows to decouple the lifetime of a proto message // from the underlying storage. It gives the following guarantees: // - The underlying message is finalized (if still alive) if the handle goes // out of scope. // - In Debug / DCHECK_ALWAYS_ON builds, the handle becomes null once the // message is finalized. This is to enforce the append-only API. For instance // when adding two repeated messages, the addition of the 2nd one forces // the finalization of the first. // Think about this as a WeakPtr which calls // Message::Finalize() when going out of scope. class PERFETTO_EXPORT MessageHandleBase { public: ~MessageHandleBase(); // Move-only type. MessageHandleBase(MessageHandleBase&&) noexcept; MessageHandleBase& operator=(MessageHandleBase&&); explicit operator bool() const { #if PERFETTO_DCHECK_IS_ON() PERFETTO_DCHECK(!message_ || generation_ == message_->generation_); #endif return !!message_; } protected: explicit MessageHandleBase(Message* = nullptr); Message* operator->() const { #if PERFETTO_DCHECK_IS_ON() PERFETTO_DCHECK(!message_ || generation_ == message_->generation_); #endif return message_; } Message& operator*() const { return *(operator->()); } private: friend class Message; MessageHandleBase(const MessageHandleBase&) = delete; MessageHandleBase& operator=(const MessageHandleBase&) = delete; void reset_message() { // This is called by Message::Finalize(). PERFETTO_DCHECK(message_->is_finalized()); message_ = nullptr; } void Move(MessageHandleBase&&); void FinalizeMessage() { message_->Finalize(); } Message* message_; #if PERFETTO_DCHECK_IS_ON() uint32_t generation_; #endif }; template class MessageHandle : public MessageHandleBase { public: MessageHandle() : MessageHandle(nullptr) {} explicit MessageHandle(T* message) : MessageHandleBase(message) {} explicit operator bool() const { return MessageHandleBase::operator bool(); } T& operator*() const { return static_cast(MessageHandleBase::operator*()); } T* operator->() const { return static_cast(MessageHandleBase::operator->()); } T* get() const { return static_cast(MessageHandleBase::operator->()); } }; } // namespace protozero #endif // INCLUDE_PERFETTO_PROTOZERO_MESSAGE_HANDLE_H_ /* * Copyright (C) 2019 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_TRACING_TRACE_WRITER_BASE_H_ #define INCLUDE_PERFETTO_TRACING_TRACE_WRITER_BASE_H_ // gen_amalgamated expanded: #include "perfetto/protozero/message_handle.h" namespace perfetto { namespace protos { namespace pbzero { class TracePacket; } // namespace pbzero } // namespace protos // The bare-minimum subset of the TraceWriter interface that is exposed as a // fully public API. // See comments in /include/perfetto/ext/tracing/core/trace_writer.h. class TraceWriterBase { public: virtual ~TraceWriterBase(); virtual protozero::MessageHandle NewTracePacket() = 0; virtual void Flush(std::function callback = {}) = 0; virtual uint64_t written() const = 0; }; } // namespace perfetto #endif // INCLUDE_PERFETTO_TRACING_TRACE_WRITER_BASE_H_ /* * Copyright (C) 2019 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_DATA_SOURCE_INTERNAL_H_ #define INCLUDE_PERFETTO_TRACING_INTERNAL_DATA_SOURCE_INTERNAL_H_ #include #include #include #include #include #include #include // No perfetto headers (other than tracing/api and protozero) should be here. // gen_amalgamated expanded: #include "perfetto/tracing/buffer_exhausted_policy.h" // gen_amalgamated expanded: #include "perfetto/tracing/internal/basic_types.h" // gen_amalgamated expanded: #include "perfetto/tracing/trace_writer_base.h" namespace perfetto { class DataSourceBase; class InterceptorBase; class TraceWriterBase; namespace internal { class TracingTLS; // This maintains the internal state of a data source instance that is used only // to implement the tracing mechanics and is not exposed to the API client. // There is one of these object per DataSource instance (up to // kMaxDataSourceInstances). struct DataSourceState { // This boolean flag determines whether the DataSource::Trace() method should // do something or be a no-op. This flag doesn't give the full guarantee // that tracing data will be visible in the trace, it just makes it so that // the client attemps writing trace data and interacting with the service. // For instance, when a tracing session ends the service will reject data // commits that arrive too late even if the producer hasn't received the stop // IPC message. // This flag is set right before calling OnStart() and cleared right before // calling OnStop(), unless using HandleStopAsynchronously() (see comments // in data_source.h). // Keep this flag as the first field. This allows the compiler to directly // dereference the DataSourceState* pointer in the trace fast-path without // doing extra pointr arithmetic. bool trace_lambda_enabled = false; // The central buffer id that all TraceWriter(s) created by this data source // must target. BufferId buffer_id = 0; // The index within TracingMuxerImpl.backends_. Practically it allows to // lookup the Producer object, and hence the IPC channel, for this data // source. TracingBackendId backend_id = 0; // Each backend may connect to the tracing service multiple times if a // disconnection occurs. This counter is used to uniquely identify each // connection so that trace writers don't get reused across connections. uint32_t backend_connection_id = 0; // The instance id as assigned by the tracing service. Note that because a // process can be connected to >1 services, this ID is not globally unique but // is only unique within the scope of its backend. // Only the tuple (backend_id, data_source_instance_id) is globally unique. uint64_t data_source_instance_id = 0; // A hash of the trace config used by this instance. This is used to // de-duplicate instances for data sources with identical names (e.g., track // event). uint64_t config_hash = 0; // If this data source is being intercepted (see Interceptor), this field // contains the non-zero id of a registered interceptor which should receive // trace packets for this session. Note: interceptor id 1 refers to the first // element of TracingMuxerImpl::interceptors_ with successive numbers using // the following slots. uint32_t interceptor_id = 0; // This lock is not held to implement Trace() and it's used only if the trace // code wants to access its own data source state. // This is to prevent that accessing the data source on an arbitrary embedder // thread races with the internal IPC thread destroying the data source // because of a end-of-tracing notification from the service. // This lock is also used to protect access to a possible interceptor for this // data source session. std::recursive_mutex lock; std::unique_ptr data_source; std::unique_ptr interceptor; }; // This is to allow lazy-initialization and avoid static initializers and // at-exit destructors. All the entries are initialized via placement-new when // DataSource::Register() is called, see TracingMuxerImpl::RegisterDataSource(). struct DataSourceStateStorage { alignas(DataSourceState) char storage[sizeof(DataSourceState)]{}; }; // Per-DataSource-type global state. struct DataSourceStaticState { // Unique index of the data source, assigned at registration time. uint32_t index = kMaxDataSources; // A bitmap that tells about the validity of each |instances| entry. When the // i-th bit of the bitmap it's set, instances[i] is valid. std::atomic valid_instances{}; std::array instances{}; // Incremented whenever incremental state should be reset for any instance of // this data source. std::atomic incremental_state_generation{}; // Can be used with a cached |valid_instances| bitmap. DataSourceState* TryGetCached(uint32_t cached_bitmap, size_t n) { return cached_bitmap & (1 << n) ? reinterpret_cast(&instances[n]) : nullptr; } DataSourceState* TryGet(size_t n) { return TryGetCached(valid_instances.load(std::memory_order_acquire), n); } void CompilerAsserts() { static_assert(sizeof(valid_instances.load()) * 8 >= kMaxDataSourceInstances, "kMaxDataSourceInstances too high"); } }; // Per-DataSource-instance thread-local state. struct DataSourceInstanceThreadLocalState { using IncrementalStatePointer = std::unique_ptr; void Reset() { trace_writer.reset(); incremental_state.reset(); backend_id = 0; backend_connection_id = 0; buffer_id = 0; data_source_instance_id = 0; incremental_state_generation = 0; is_intercepted = false; } std::unique_ptr trace_writer; IncrementalStatePointer incremental_state = {nullptr, [](void*) {}}; uint32_t incremental_state_generation; TracingBackendId backend_id; uint32_t backend_connection_id; BufferId buffer_id; uint64_t data_source_instance_id; bool is_intercepted; }; // Per-DataSource-type thread-local state. struct DataSourceThreadLocalState { DataSourceStaticState* static_state = nullptr; // Pointer to the parent tls object that holds us. Used to retrieve the // generation, which is per-global-TLS and not per data-source. TracingTLS* root_tls = nullptr; // One entry per each data source instance. std::array per_instance{}; }; } // namespace internal } // namespace perfetto #endif // INCLUDE_PERFETTO_TRACING_INTERNAL_DATA_SOURCE_INTERNAL_H_ // gen_amalgamated begin header: include/perfetto/tracing/locked_handle.h /* * Copyright (C) 2019 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_TRACING_LOCKED_HANDLE_H_ #define INCLUDE_PERFETTO_TRACING_LOCKED_HANDLE_H_ #include namespace perfetto { // This is used for GetDataSourceLocked(), in the (rare) case where the // tracing code wants to access the state of its data source from the Trace() // method. template class LockedHandle { public: LockedHandle(std::recursive_mutex* mtx, T* obj) : lock_(*mtx), obj_(obj) {} LockedHandle() = default; // For the invalid case. LockedHandle(LockedHandle&&) = default; LockedHandle& operator=(LockedHandle&&) = default; bool valid() const { return obj_; } explicit operator bool() const { return valid(); } T* operator->() { assert(valid()); return obj_; } T& operator*() { return *(this->operator->()); } private: std::unique_lock lock_; T* obj_ = nullptr; }; } // namespace perfetto #endif // INCLUDE_PERFETTO_TRACING_LOCKED_HANDLE_H_ /* * Copyright (C) 2020 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_TRACING_INTERCEPTOR_H_ #define INCLUDE_PERFETTO_TRACING_INTERCEPTOR_H_ // An interceptor is used to redirect trace packets written by a data source // into a custom backend instead of the normal Perfetto tracing service. For // example, the console interceptor prints all trace packets to the console as // they are generated. Another potential use is exporting trace data to another // tracing service such as Android ATrace or Windows ETW. // // An interceptor is defined by subclassing the perfetto::Interceptor template: // // class MyInterceptor : public perfetto::Interceptor { // public: // ~MyInterceptor() override = default; // // // This function is called for each intercepted trace packet. |context| // // contains information about the trace packet as well as other state // // tracked by the interceptor (e.g., see ThreadLocalState). // // // // Intercepted trace data is provided in the form of serialized protobuf // // bytes, accessed through the |context.packet_data| field. // // // // Warning: this function can be called on any thread at any time. See // // below for how to safely access shared interceptor data from here. // static void OnTracePacket(InterceptorContext context) { // perfetto::protos::pbzero::TracePacket::Decoder packet( // context.packet_data.data, context.packet_data.size); // // ... Write |packet| to the desired destination ... // } // }; // // An interceptor should be registered before any tracing sessions are started. // Note that the interceptor also needs to be activated through the trace config // as shown below. // // perfetto::InterceptorDescriptor desc; // desc.set_name("my_interceptor"); // MyInterceptor::Register(desc); // // Finally, an interceptor is enabled through the trace config like this: // // perfetto::TraceConfig cfg; // auto* ds_cfg = cfg.add_data_sources()->mutable_config(); // ds_cfg->set_name("data_source_to_intercept"); // e.g. "track_event" // ds_cfg->mutable_interceptor_config()->set_name("my_interceptor"); // // Once an interceptor is enabled, all data from the affected data sources is // sent to the interceptor instead of the main tracing buffer. // // Interceptor state // ================= // // Besides the serialized trace packet data, the |OnTracePacket| interceptor // function can access three other types of state: // // 1. Global state: this is no different from a normal static function, but care // must be taken because |OnTracePacket| can be called concurrently on any // thread at any time. // // 2. Per-data source instance state: since the interceptor class is // automatically instantiated for each intercepted data source, its fields // can be used to store per-instance data such as the trace config. This data // can be maintained through the OnSetup/OnStart/OnStop callbacks: // // class MyInterceptor : public perfetto::Interceptor { // public: // void OnSetup(const SetupArgs& args) override { // enable_foo_ = args.config.interceptor_config().enable_foo(); // } // // bool enable_foo_{}; // }; // // In the interceptor function this data must be accessed through a scoped // lock for safety: // // class MyInterceptor : public perfetto::Interceptor { // ... // static void OnTracePacket(InterceptorContext context) { // auto my_interceptor = context.GetInterceptorLocked(); // if (my_interceptor) { // // Access fields of MyInterceptor here. // if (my_interceptor->enable_foo_) { ... } // } // ... // } // }; // // Since accessing this data involves holding a lock, it should be done // sparingly. // // 3. Per-thread/TraceWriter state: many data sources use interning to avoid // repeating common data in the trace. Since the interning dictionaries are // typically kept individually for each TraceWriter sequence (i.e., per // thread), an interceptor can declare a data structure with lifetime // matching the TraceWriter: // // class MyInterceptor : public perfetto::Interceptor { // public: // struct ThreadLocalState // : public perfetto::InterceptorBase::ThreadLocalState { // ThreadLocalState(ThreadLocalStateArgs&) override = default; // ~ThreadLocalState() override = default; // // std::map event_names; // }; // }; // // This per-thread state can then be accessed and maintained in // |OnTracePacket| like this: // // class MyInterceptor : public perfetto::Interceptor { // ... // static void OnTracePacket(InterceptorContext context) { // // Updating interned data. // auto& tls = context.GetThreadLocalState(); // if (parsed_packet.sequence_flags() & perfetto::protos::pbzero:: // TracePacket::SEQ_INCREMENTAL_STATE_CLEARED) { // tls.event_names.clear(); // } // for (const auto& entry : parsed_packet.interned_data().event_names()) // tls.event_names[entry.iid()] = entry.name(); // // // Looking up interned data. // if (parsed_packet.has_track_event()) { // size_t name_iid = parsed_packet.track_event().name_iid(); // const std::string& event_name = tls.event_names[name_iid]; // } // ... // } // }; // #include // gen_amalgamated expanded: #include "perfetto/protozero/field.h" // gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h" // gen_amalgamated expanded: #include "perfetto/tracing/internal/basic_types.h" // gen_amalgamated expanded: #include "perfetto/tracing/internal/data_source_internal.h" // gen_amalgamated expanded: #include "perfetto/tracing/locked_handle.h" namespace { class MockTracingMuxer; } namespace perfetto { namespace protos { namespace gen { class DataSourceConfig; class InterceptorDescriptor; } // namespace gen } // namespace protos using protos::gen::InterceptorDescriptor; namespace internal { class InterceptorTraceWriter; class TracingMuxer; class TracingMuxerFake; class TracingMuxerImpl; } // namespace internal // A virtual base class for interceptors. Users should derive from the templated // subclass below instead of this one. class PERFETTO_EXPORT InterceptorBase { public: virtual ~InterceptorBase(); // A virtual base class for thread-local state needed by the interceptor. // To define your own state, subclass this with the same name in the // interceptor class. A reference to the state can then be looked up through // context.GetThreadLocalState() in the trace packet interceptor function. class ThreadLocalState { public: virtual ~ThreadLocalState(); }; struct SetupArgs { const DataSourceConfig& config; }; struct StartArgs {}; struct StopArgs {}; // Called when an intercepted data source is set up. Both the interceptor's // and the data source's configuration is available in // |SetupArgs|. Called on an internal Perfetto service thread, but not // concurrently. virtual void OnSetup(const SetupArgs&) {} // Called when an intercepted data source starts. Called on an internal // Perfetto service thread, but not concurrently. virtual void OnStart(const StartArgs&) {} // Called when an intercepted data source stops. Called on an internal // Perfetto service thread, but not concurrently. virtual void OnStop(const StopArgs&) {} private: friend class internal::InterceptorTraceWriter; friend class internal::TracingMuxer; friend class internal::TracingMuxerFake; friend class internal::TracingMuxerImpl; friend MockTracingMuxer; template friend class Interceptor; // Data passed from DataSource::Trace() into the interceptor. struct TracePacketCallbackArgs { internal::DataSourceStaticState* static_state; uint32_t instance_index; protozero::ConstBytes packet_data; ThreadLocalState* tls; }; // These callback functions are defined as stateless to avoid accidentally // introducing cross-thread data races. using TLSFactory = std::unique_ptr (*)( internal::DataSourceStaticState*, uint32_t data_source_instance_index); using TracePacketCallback = void (*)(TracePacketCallbackArgs); static void RegisterImpl( const InterceptorDescriptor& descriptor, std::function()> factory, InterceptorBase::TLSFactory tls_factory, InterceptorBase::TracePacketCallback on_trace_packet); }; // Templated interceptor instantiation. See above for usage. template class PERFETTO_EXPORT Interceptor : public InterceptorBase { public: // A context object provided to the ThreadLocalState constructor. Provides // access to the per-instance interceptor object. class ThreadLocalStateArgs { public: ~ThreadLocalStateArgs() = default; // Return a locked reference to the interceptor session. The session object // will remain valid as long as the returned handle is in scope. LockedHandle GetInterceptorLocked() { auto* internal_state = static_state_->TryGet(data_source_instance_index_); if (!internal_state) return LockedHandle(); return LockedHandle( &internal_state->lock, static_cast(internal_state->interceptor.get())); } private: friend class Interceptor; friend class InterceptorContext; friend class TracingMuxerImpl; ThreadLocalStateArgs(internal::DataSourceStaticState* static_state, uint32_t data_source_instance_index) : static_state_(static_state), data_source_instance_index_(data_source_instance_index) {} internal::DataSourceStaticState* const static_state_; const uint32_t data_source_instance_index_; }; // A context object provided to each call into |OnTracePacket|. Contains the // intercepted serialized trace packet data. class InterceptorContext { public: InterceptorContext(InterceptorContext&&) noexcept = default; ~InterceptorContext() = default; // Return a locked reference to the interceptor session. The session object // will remain valid as long as the returned handle is in scope. LockedHandle GetInterceptorLocked() { return tls_args_.GetInterceptorLocked(); } // Return the thread-local state for this interceptor. See // InterceptorBase::ThreadLocalState. typename InterceptorType::ThreadLocalState& GetThreadLocalState() { return static_cast(*tls_); } // A buffer containing the serialized TracePacket protocol buffer message. // This memory is only valid during the call to OnTracePacket. protozero::ConstBytes packet_data; private: friend class Interceptor; InterceptorContext(TracePacketCallbackArgs args) : packet_data(args.packet_data), tls_args_(args.static_state, args.instance_index), tls_(args.tls) {} InterceptorContext(const InterceptorContext&) = delete; InterceptorContext& operator=(const InterceptorContext&) = delete; ThreadLocalStateArgs tls_args_; InterceptorBase::ThreadLocalState* const tls_; }; // Register the interceptor for use in tracing sessions. // The optional |constructor_args| will be passed to the interceptor when it // is constructed. template static void Register(const InterceptorDescriptor& descriptor, const Args&... constructor_args) { auto factory = [constructor_args...]() { return std::unique_ptr( new InterceptorType(constructor_args...)); }; auto tls_factory = [](internal::DataSourceStaticState* static_state, uint32_t data_source_instance_index) { // Don't bother allocating TLS state unless the interceptor is actually // using it. if (std::is_same::value) { return std::unique_ptr(nullptr); } ThreadLocalStateArgs args(static_state, data_source_instance_index); return std::unique_ptr( new typename InterceptorType::ThreadLocalState(args)); }; auto on_trace_packet = [](TracePacketCallbackArgs args) { InterceptorType::OnTracePacket(InterceptorContext(std::move(args))); }; RegisterImpl(descriptor, std::move(factory), std::move(tls_factory), std::move(on_trace_packet)); } }; } // namespace perfetto #endif // INCLUDE_PERFETTO_TRACING_INTERCEPTOR_H_ // gen_amalgamated begin header: include/perfetto/tracing/track_event_state_tracker.h // gen_amalgamated begin header: gen/protos/perfetto/trace/track_event/track_event.pbzero.h // gen_amalgamated begin header: include/perfetto/protozero/field_writer.h /* * Copyright (C) 2021 The Android Open Source Project * * 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. */ // gen_amalgamated expanded: #include "perfetto/protozero/message.h" // gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h" #ifndef INCLUDE_PERFETTO_PROTOZERO_FIELD_WRITER_H_ #define INCLUDE_PERFETTO_PROTOZERO_FIELD_WRITER_H_ namespace protozero { namespace internal { template struct FieldWriter { static_assert(proto_schema_type != proto_utils::ProtoSchemaType::kMessage, "FieldWriter can't be used with nested messages"); }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, double value) { message.AppendFixed(field_id, value); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, float value) { message.AppendFixed(field_id, value); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, bool value) { message.AppendTinyVarInt(field_id, value); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, int32_t value) { message.AppendVarInt(field_id, value); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, int64_t value) { message.AppendVarInt(field_id, value); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, uint32_t value) { message.AppendVarInt(field_id, value); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, uint64_t value) { message.AppendVarInt(field_id, value); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, int32_t value) { message.AppendSignedVarInt(field_id, value); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, int64_t value) { message.AppendSignedVarInt(field_id, value); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, uint32_t value) { message.AppendFixed(field_id, value); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, uint64_t value) { message.AppendFixed(field_id, value); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, int32_t value) { message.AppendFixed(field_id, value); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, int64_t value) { message.AppendFixed(field_id, value); } }; template <> struct FieldWriter { template inline static void Append(Message& message, uint32_t field_id, EnumType value) { message.AppendVarInt(field_id, value); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, const char* data, size_t size) { message.AppendBytes(field_id, data, size); } inline static void Append(Message& message, uint32_t field_id, const std::string& value) { message.AppendBytes(field_id, value.data(), value.size()); } }; template <> struct FieldWriter { inline static void Append(Message& message, uint32_t field_id, const uint8_t* data, size_t size) { message.AppendBytes(field_id, data, size); } inline static void Append(Message& message, uint32_t field_id, const std::string& value) { message.AppendBytes(field_id, value.data(), value.size()); } }; } // namespace internal } // namespace protozero #endif // INCLUDE_PERFETTO_PROTOZERO_FIELD_WRITER_H_ // gen_amalgamated begin header: include/perfetto/protozero/packed_repeated_fields.h /* * Copyright (C) 2019 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_PROTOZERO_PACKED_REPEATED_FIELDS_H_ #define INCLUDE_PERFETTO_PROTOZERO_PACKED_REPEATED_FIELDS_H_ #include #include #include #include // gen_amalgamated expanded: #include "perfetto/base/logging.h" // gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h" namespace protozero { // This file contains classes used when encoding packed repeated fields. // To encode such a field, the caller is first expected to accumulate all of the // values in one of the following types (depending on the wire type of the // individual elements), defined below: // * protozero::PackedVarInt // * protozero::PackedFixedSizeInt // Then that buffer is passed to the protozero-generated setters as an argument. // After calling the setter, the buffer can be destroyed. // // An example of encoding a packed field: // protozero::HeapBuffered msg; // protozero::PackedVarInt buf; // buf.Append(42); // buf.Append(-1); // msg->set_fieldname(buf); // msg.SerializeAsString(); class PackedBufferBase { public: PackedBufferBase() { Reset(); } // Copy or move is disabled due to pointers to stack addresses. PackedBufferBase(const PackedBufferBase&) = delete; PackedBufferBase(PackedBufferBase&&) = delete; PackedBufferBase& operator=(const PackedBufferBase&) = delete; PackedBufferBase& operator=(PackedBufferBase&&) = delete; void Reset(); const uint8_t* data() const { return storage_begin_; } size_t size() const { return static_cast(write_ptr_ - storage_begin_); } protected: void GrowIfNeeded() { PERFETTO_DCHECK(write_ptr_ >= storage_begin_ && write_ptr_ <= storage_end_); if (PERFETTO_UNLIKELY(write_ptr_ + kMaxElementSize > storage_end_)) { GrowSlowpath(); } } void GrowSlowpath(); // max(uint64_t varint encoding, biggest fixed type (uint64)). static constexpr size_t kMaxElementSize = 10; // So sizeof(this) == 8k. static constexpr size_t kOnStackStorageSize = 8192 - 32; uint8_t* storage_begin_; uint8_t* storage_end_; uint8_t* write_ptr_; std::unique_ptr heap_buf_; alignas(uint64_t) uint8_t stack_buf_[kOnStackStorageSize]; }; class PackedVarInt : public PackedBufferBase { public: template void Append(T value) { GrowIfNeeded(); write_ptr_ = proto_utils::WriteVarInt(value, write_ptr_); } }; template class PackedFixedSizeInt : public PackedBufferBase { public: void Append(T value) { static_assert(sizeof(T) == 4 || sizeof(T) == 8, "PackedFixedSizeInt should be used only with 32/64-bit ints"); static_assert(sizeof(T) <= kMaxElementSize, "kMaxElementSize needs to be updated"); GrowIfNeeded(); PERFETTO_DCHECK(reinterpret_cast(write_ptr_) % alignof(T) == 0); memcpy(reinterpret_cast(write_ptr_), &value, sizeof(T)); write_ptr_ += sizeof(T); } }; } // namespace protozero #endif // INCLUDE_PERFETTO_PROTOZERO_PACKED_REPEATED_FIELDS_H_ // gen_amalgamated begin header: include/perfetto/protozero/proto_decoder.h /* * Copyright (C) 2018 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_PROTOZERO_PROTO_DECODER_H_ #define INCLUDE_PERFETTO_PROTOZERO_PROTO_DECODER_H_ #include #include #include #include // gen_amalgamated expanded: #include "perfetto/base/compiler.h" // gen_amalgamated expanded: #include "perfetto/base/logging.h" // gen_amalgamated expanded: #include "perfetto/protozero/field.h" // gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h" namespace protozero { // A generic protobuf decoder. Doesn't require any knowledge about the proto // schema. It tokenizes fields, retrieves their ID and type and exposes // accessors to retrieve its values. // It does NOT recurse in nested submessages, instead it just computes their // boundaries, recursion is left to the caller. // This class is designed to be used in perf-sensitive contexts. It does not // allocate and does not perform any proto semantic checks (e.g. repeated / // required / optional). It's supposedly safe wrt out-of-bounds memory accesses // (see proto_decoder_fuzzer.cc). // This class serves also as a building block for TypedProtoDecoder, used when // the schema is known at compile time. class PERFETTO_EXPORT ProtoDecoder { public: // Creates a ProtoDecoder using the given |buffer| with size |length| bytes. ProtoDecoder(const void* buffer, size_t length) : begin_(reinterpret_cast(buffer)), end_(begin_ + length), read_ptr_(begin_) {} ProtoDecoder(const std::string& str) : ProtoDecoder(str.data(), str.size()) {} ProtoDecoder(const ConstBytes& cb) : ProtoDecoder(cb.data, cb.size) {} // Reads the next field from the buffer and advances the read cursor. If a // full field cannot be read, the returned Field will be invalid (i.e. // field.valid() == false). Field ReadField(); // Finds the first field with the given id. Doesn't affect the read cursor. Field FindField(uint32_t field_id); // Resets the read cursor to the start of the buffer. void Reset() { read_ptr_ = begin_; } // Resets the read cursor to the given position (must be within the buffer). void Reset(const uint8_t* pos) { PERFETTO_DCHECK(pos >= begin_ && pos < end_); read_ptr_ = pos; } // Returns the position of read cursor, relative to the start of the buffer. size_t read_offset() const { return static_cast(read_ptr_ - begin_); } size_t bytes_left() const { PERFETTO_DCHECK(read_ptr_ <= end_); return static_cast(end_ - read_ptr_); } const uint8_t* begin() const { return begin_; } const uint8_t* end() const { return end_; } protected: const uint8_t* const begin_; const uint8_t* const end_; const uint8_t* read_ptr_ = nullptr; }; // An iterator-like class used to iterate through repeated fields. Used by // TypedProtoDecoder. The iteration sequence is a bit counter-intuitive due to // the fact that fields_[field_id] holds the *last* value of the field, not the // first, but the remaining storage holds repeated fields in FIFO order. // Assume that we push the 10,11,12 into a repeated field with ID=1. // // Decoder memory layout: [ fields storage ] [ repeated fields storage ] // 1st iteration: 10 // 2nd iteration: 11 10 // 3rd iteration: 12 10 11 // // We start the iteration @ fields_[num_fields], which is the start of the // repeated fields storage, proceed until the end and lastly jump @ fields_[id]. template class RepeatedFieldIterator { public: RepeatedFieldIterator(uint32_t field_id, const Field* begin, const Field* end, const Field* last) : field_id_(field_id), iter_(begin), end_(end), last_(last) { FindNextMatchingId(); } // Constructs an invalid iterator. RepeatedFieldIterator() : field_id_(0u), iter_(nullptr), end_(nullptr), last_(nullptr) {} explicit operator bool() const { return iter_ != end_; } const Field& field() const { return *iter_; } T operator*() const { T val{}; iter_->get(&val); return val; } const Field* operator->() const { return iter_; } RepeatedFieldIterator& operator++() { PERFETTO_DCHECK(iter_ != end_); if (iter_ == last_) { iter_ = end_; return *this; } ++iter_; FindNextMatchingId(); return *this; } RepeatedFieldIterator operator++(int) { PERFETTO_DCHECK(iter_ != end_); RepeatedFieldIterator it(*this); ++(*this); return it; } private: void FindNextMatchingId() { PERFETTO_DCHECK(iter_ != last_); for (; iter_ != end_; ++iter_) { if (iter_->id() == field_id_) return; } iter_ = last_->valid() ? last_ : end_; } uint32_t field_id_; // Initially points to the beginning of the repeated field storage, then is // incremented as we call operator++(). const Field* iter_; // Always points to fields_[size_], i.e. past the end of the storage. const Field* end_; // Always points to fields_[field_id]. const Field* last_; }; // As RepeatedFieldIterator, but allows iterating over a packed repeated field // (which will be initially stored as a single length-delimited field). // See |GetPackedRepeatedField| for details. // // Assumes little endianness, and that the input buffers are well formed - // containing an exact multiple of encoded elements. template class PackedRepeatedFieldIterator { public: PackedRepeatedFieldIterator(const uint8_t* data_begin, size_t size, bool* parse_error_ptr) : data_end_(data_begin ? data_begin + size : nullptr), read_ptr_(data_begin), parse_error_(parse_error_ptr) { using proto_utils::ProtoWireType; static_assert(wire_type == ProtoWireType::kVarInt || wire_type == ProtoWireType::kFixed32 || wire_type == ProtoWireType::kFixed64, "invalid type"); PERFETTO_DCHECK(parse_error_ptr); // Either the field is unset (and there are no data pointer), or the field // is set with a zero length payload. Mark the iterator as invalid in both // cases. if (size == 0) { curr_value_valid_ = false; return; } if ((wire_type == ProtoWireType::kFixed32 && (size % 4) != 0) || (wire_type == ProtoWireType::kFixed64 && (size % 8) != 0)) { *parse_error_ = true; curr_value_valid_ = false; return; } ++(*this); } const CppType operator*() const { return curr_value_; } explicit operator bool() const { return curr_value_valid_; } PackedRepeatedFieldIterator& operator++() { using proto_utils::ProtoWireType; if (PERFETTO_UNLIKELY(!curr_value_valid_)) return *this; if (PERFETTO_UNLIKELY(read_ptr_ == data_end_)) { curr_value_valid_ = false; return *this; } if (wire_type == ProtoWireType::kVarInt) { uint64_t new_value = 0; const uint8_t* new_pos = proto_utils::ParseVarInt(read_ptr_, data_end_, &new_value); if (PERFETTO_UNLIKELY(new_pos == read_ptr_)) { // Failed to decode the varint (probably incomplete buffer). *parse_error_ = true; curr_value_valid_ = false; } else { read_ptr_ = new_pos; curr_value_ = static_cast(new_value); } } else { // kFixed32 or kFixed64 constexpr size_t kStep = wire_type == ProtoWireType::kFixed32 ? 4 : 8; // NB: the raw buffer is not guaranteed to be aligned, so neither are // these copies. memcpy(&curr_value_, read_ptr_, sizeof(CppType)); read_ptr_ += kStep; } return *this; } PackedRepeatedFieldIterator operator++(int) { PackedRepeatedFieldIterator it(*this); ++(*this); return it; } private: // Might be null if the backing proto field isn't set. const uint8_t* const data_end_; // The iterator looks ahead by an element, so |curr_value| holds the value // to be returned when the caller dereferences the iterator, and |read_ptr_| // points at the start of the next element to be decoded. // |read_ptr_| might be null if the backing proto field isn't set. const uint8_t* read_ptr_; CppType curr_value_ = 0; // Set to false once we've exhausted the iterator, or encountered an error. bool curr_value_valid_ = true; // Where to set parsing errors, supplied by the caller. bool* const parse_error_; }; // This decoder loads all fields upfront, without recursing in nested messages. // It is used as a base class for typed decoders generated by the pbzero plugin. // The split between TypedProtoDecoderBase and TypedProtoDecoder<> is to have // unique definition of functions like ParseAllFields() and ExpandHeapStorage(). // The storage (either on-stack or on-heap) for this class is organized as // follows: // |-------------------------- fields_ ----------------------| // [ field 0 (invalid) ] [ fields 1 .. N ] [ repeated fields ] // ^ ^ // num_fields_ size_ class PERFETTO_EXPORT TypedProtoDecoderBase : public ProtoDecoder { public: // If the field |id| is known at compile time, prefer the templated // specialization at(). const Field& Get(uint32_t id) const { return PERFETTO_LIKELY(id < num_fields_) ? fields_[id] : fields_[0]; } // Returns an object that allows to iterate over all instances of a repeated // field given its id. Example usage: // for (auto it = decoder.GetRepeated(N); it; ++it) { ... } template RepeatedFieldIterator GetRepeated(uint32_t field_id) const { return RepeatedFieldIterator(field_id, &fields_[num_fields_], &fields_[size_], &fields_[field_id]); } // Returns an objects that allows to iterate over all entries of a packed // repeated field given its id and type. The |wire_type| is necessary for // decoding the packed field, the |cpp_type| is for convenience & stronger // typing. // // The caller must also supply a pointer to a bool that is set to true if the // packed buffer is found to be malformed while iterating (so you need to // exhaust the iterator if you want to check the full extent of the buffer). // // Note that unlike standard protobuf parsers, protozero does not allow // treating of packed repeated fields as non-packed and vice-versa (therefore // not making the packed option forwards and backwards compatible). So // the caller needs to use the right accessor for correct results. template PackedRepeatedFieldIterator GetPackedRepeated( uint32_t field_id, bool* parse_error_location) const { const Field& field = Get(field_id); if (field.valid()) { return PackedRepeatedFieldIterator( field.data(), field.size(), parse_error_location); } else { return PackedRepeatedFieldIterator( nullptr, 0, parse_error_location); } } protected: TypedProtoDecoderBase(Field* storage, uint32_t num_fields, uint32_t capacity, const uint8_t* buffer, size_t length) : ProtoDecoder(buffer, length), fields_(storage), num_fields_(num_fields), size_(num_fields), capacity_(capacity) { // The reason why Field needs to be trivially de/constructible is to avoid // implicit initializers on all the ~1000 entries. We need it to initialize // only on the first |max_field_id| fields, the remaining capacity doesn't // require initialization. static_assert(std::is_trivially_constructible::value && std::is_trivially_destructible::value && std::is_trivial::value, "Field must be a trivial aggregate type"); memset(fields_, 0, sizeof(Field) * num_fields_); } void ParseAllFields(); // Called when the default on-stack storage is exhausted and new repeated // fields need to be pushed. void ExpandHeapStorage(); // Used only in presence of a large number of repeated fields, when the // default on-stack storage is exhausted. std::unique_ptr heap_storage_; // Points to the storage, either on-stack (default, provided by the template // specialization) or |heap_storage_| after ExpandHeapStorage() is called, in // case of a large number of repeated fields. Field* fields_; // Number of fields without accounting repeated storage. This is equal to // MAX_FIELD_ID + 1 (to account for the invalid 0th field). // This value is always <= size_ (and hence <= capacity); uint32_t num_fields_; // Number of active |fields_| entries. This is initially equal to the highest // number of fields for the message (num_fields_ == MAX_FIELD_ID + 1) and can // grow up to |capacity_| in the case of repeated fields. uint32_t size_; // Initially equal to kFieldsCapacity of the TypedProtoDecoder // specialization. Can grow when falling back on heap-based storage, in which // case it represents the size (#fields with each entry of a repeated field // counted individually) of the |heap_storage_| array. uint32_t capacity_; }; // Template class instantiated by the auto-generated decoder classes declared in // xxx.pbzero.h files. template class TypedProtoDecoder : public TypedProtoDecoderBase { public: TypedProtoDecoder(const uint8_t* buffer, size_t length) : TypedProtoDecoderBase(on_stack_storage_, /*num_fields=*/MAX_FIELD_ID + 1, kCapacity, buffer, length) { static_assert(MAX_FIELD_ID <= kMaxDecoderFieldId, "Field ordinal too high"); TypedProtoDecoderBase::ParseAllFields(); } template const Field& at() const { static_assert(FIELD_ID <= MAX_FIELD_ID, "FIELD_ID > MAX_FIELD_ID"); return fields_[FIELD_ID]; } TypedProtoDecoder(TypedProtoDecoder&& other) noexcept : TypedProtoDecoderBase(std::move(other)) { // If the moved-from decoder was using on-stack storage, we need to update // our pointer to point to this decoder's on-stack storage. if (fields_ == other.on_stack_storage_) { fields_ = on_stack_storage_; memcpy(on_stack_storage_, other.on_stack_storage_, sizeof(on_stack_storage_)); } } private: // In the case of non-repeated fields, this constant defines the highest field // id we are able to decode. This is to limit the on-stack storage. // In the case of repeated fields, this constant defines the max number of // repeated fields that we'll be able to store before falling back on the // heap. Keep this value in sync with the one in protozero_generator.cc. static constexpr size_t kMaxDecoderFieldId = 999; // If we the message has no repeated fields we need at most N Field entries // in the on-stack storage, where N is the highest field id. // Otherwise we need some room to store repeated fields. static constexpr size_t kCapacity = 1 + (HAS_NONPACKED_REPEATED_FIELDS ? kMaxDecoderFieldId : MAX_FIELD_ID); Field on_stack_storage_[kCapacity]; }; } // namespace protozero #endif // INCLUDE_PERFETTO_PROTOZERO_PROTO_DECODER_H_ // Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT. #ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TRACK_EVENT_PROTO_H_ #define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TRACK_EVENT_PROTO_H_ #include #include // gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h" // gen_amalgamated expanded: #include "perfetto/protozero/message.h" // gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h" // gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h" // gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h" namespace perfetto { namespace protos { namespace pbzero { class ChromeApplicationStateInfo; class ChromeCompositorSchedulerState; class ChromeContentSettingsEventInfo; class ChromeFrameReporter; class ChromeHistogramSample; class ChromeKeyedService; class ChromeLatencyInfo; class ChromeLegacyIpc; class ChromeMessagePump; class ChromeMojoEventInfo; class ChromeRendererSchedulerState; class ChromeUserEvent; class ChromeWindowHandleEventInfo; class DebugAnnotation; class LogMessage; class SourceLocation; class TaskExecution; class TrackEvent_LegacyEvent; enum TrackEvent_LegacyEvent_FlowDirection : int32_t; enum TrackEvent_LegacyEvent_InstantEventScope : int32_t; enum TrackEvent_Type : int32_t; enum TrackEvent_Type : int32_t { TrackEvent_Type_TYPE_UNSPECIFIED = 0, TrackEvent_Type_TYPE_SLICE_BEGIN = 1, TrackEvent_Type_TYPE_SLICE_END = 2, TrackEvent_Type_TYPE_INSTANT = 3, TrackEvent_Type_TYPE_COUNTER = 4, }; const TrackEvent_Type TrackEvent_Type_MIN = TrackEvent_Type_TYPE_UNSPECIFIED; const TrackEvent_Type TrackEvent_Type_MAX = TrackEvent_Type_TYPE_COUNTER; enum TrackEvent_LegacyEvent_FlowDirection : int32_t { TrackEvent_LegacyEvent_FlowDirection_FLOW_UNSPECIFIED = 0, TrackEvent_LegacyEvent_FlowDirection_FLOW_IN = 1, TrackEvent_LegacyEvent_FlowDirection_FLOW_OUT = 2, TrackEvent_LegacyEvent_FlowDirection_FLOW_INOUT = 3, }; const TrackEvent_LegacyEvent_FlowDirection TrackEvent_LegacyEvent_FlowDirection_MIN = TrackEvent_LegacyEvent_FlowDirection_FLOW_UNSPECIFIED; const TrackEvent_LegacyEvent_FlowDirection TrackEvent_LegacyEvent_FlowDirection_MAX = TrackEvent_LegacyEvent_FlowDirection_FLOW_INOUT; enum TrackEvent_LegacyEvent_InstantEventScope : int32_t { TrackEvent_LegacyEvent_InstantEventScope_SCOPE_UNSPECIFIED = 0, TrackEvent_LegacyEvent_InstantEventScope_SCOPE_GLOBAL = 1, TrackEvent_LegacyEvent_InstantEventScope_SCOPE_PROCESS = 2, TrackEvent_LegacyEvent_InstantEventScope_SCOPE_THREAD = 3, }; const TrackEvent_LegacyEvent_InstantEventScope TrackEvent_LegacyEvent_InstantEventScope_MIN = TrackEvent_LegacyEvent_InstantEventScope_SCOPE_UNSPECIFIED; const TrackEvent_LegacyEvent_InstantEventScope TrackEvent_LegacyEvent_InstantEventScope_MAX = TrackEvent_LegacyEvent_InstantEventScope_SCOPE_THREAD; class EventName_Decoder : public ::protozero::TypedProtoDecoder { public: EventName_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {} explicit EventName_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast(raw.data()), raw.size()) {} explicit EventName_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {} bool has_iid() const { return at<1>().valid(); } uint64_t iid() const { return at<1>().as_uint64(); } bool has_name() const { return at<2>().valid(); } ::protozero::ConstChars name() const { return at<2>().as_string(); } }; class EventName : public ::protozero::Message { public: using Decoder = EventName_Decoder; enum : int32_t { kIidFieldNumber = 1, kNameFieldNumber = 2, }; using FieldMetadata_Iid = ::protozero::proto_utils::FieldMetadata< 1, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kUint64, uint64_t, EventName>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_Iid kIid() { return {}; } void set_iid(uint64_t value) { static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kUint64> ::Append(*this, field_id, value); } using FieldMetadata_Name = ::protozero::proto_utils::FieldMetadata< 2, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kString, std::string, EventName>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_Name kName() { return {}; } void set_name(const char* data, size_t size) { AppendBytes(FieldMetadata_Name::kFieldId, data, size); } void set_name(std::string value) { static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kString> ::Append(*this, field_id, value); } }; class EventCategory_Decoder : public ::protozero::TypedProtoDecoder { public: EventCategory_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {} explicit EventCategory_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast(raw.data()), raw.size()) {} explicit EventCategory_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {} bool has_iid() const { return at<1>().valid(); } uint64_t iid() const { return at<1>().as_uint64(); } bool has_name() const { return at<2>().valid(); } ::protozero::ConstChars name() const { return at<2>().as_string(); } }; class EventCategory : public ::protozero::Message { public: using Decoder = EventCategory_Decoder; enum : int32_t { kIidFieldNumber = 1, kNameFieldNumber = 2, }; using FieldMetadata_Iid = ::protozero::proto_utils::FieldMetadata< 1, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kUint64, uint64_t, EventCategory>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_Iid kIid() { return {}; } void set_iid(uint64_t value) { static constexpr uint32_t field_id = FieldMetadata_Iid::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kUint64> ::Append(*this, field_id, value); } using FieldMetadata_Name = ::protozero::proto_utils::FieldMetadata< 2, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kString, std::string, EventCategory>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_Name kName() { return {}; } void set_name(const char* data, size_t size) { AppendBytes(FieldMetadata_Name::kFieldId, data, size); } void set_name(std::string value) { static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kString> ::Append(*this, field_id, value); } }; class TrackEventDefaults_Decoder : public ::protozero::TypedProtoDecoder { public: TrackEventDefaults_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {} explicit TrackEventDefaults_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast(raw.data()), raw.size()) {} explicit TrackEventDefaults_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {} bool has_track_uuid() const { return at<11>().valid(); } uint64_t track_uuid() const { return at<11>().as_uint64(); } bool has_extra_counter_track_uuids() const { return at<31>().valid(); } ::protozero::RepeatedFieldIterator extra_counter_track_uuids() const { return GetRepeated(31); } bool has_extra_double_counter_track_uuids() const { return at<45>().valid(); } ::protozero::RepeatedFieldIterator extra_double_counter_track_uuids() const { return GetRepeated(45); } }; class TrackEventDefaults : public ::protozero::Message { public: using Decoder = TrackEventDefaults_Decoder; enum : int32_t { kTrackUuidFieldNumber = 11, kExtraCounterTrackUuidsFieldNumber = 31, kExtraDoubleCounterTrackUuidsFieldNumber = 45, }; using FieldMetadata_TrackUuid = ::protozero::proto_utils::FieldMetadata< 11, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kUint64, uint64_t, TrackEventDefaults>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_TrackUuid kTrackUuid() { return {}; } void set_track_uuid(uint64_t value) { static constexpr uint32_t field_id = FieldMetadata_TrackUuid::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kUint64> ::Append(*this, field_id, value); } using FieldMetadata_ExtraCounterTrackUuids = ::protozero::proto_utils::FieldMetadata< 31, ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked, ::protozero::proto_utils::ProtoSchemaType::kUint64, uint64_t, TrackEventDefaults>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ExtraCounterTrackUuids kExtraCounterTrackUuids() { return {}; } void add_extra_counter_track_uuids(uint64_t value) { static constexpr uint32_t field_id = FieldMetadata_ExtraCounterTrackUuids::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kUint64> ::Append(*this, field_id, value); } using FieldMetadata_ExtraDoubleCounterTrackUuids = ::protozero::proto_utils::FieldMetadata< 45, ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked, ::protozero::proto_utils::ProtoSchemaType::kUint64, uint64_t, TrackEventDefaults>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ExtraDoubleCounterTrackUuids kExtraDoubleCounterTrackUuids() { return {}; } void add_extra_double_counter_track_uuids(uint64_t value) { static constexpr uint32_t field_id = FieldMetadata_ExtraDoubleCounterTrackUuids::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kUint64> ::Append(*this, field_id, value); } }; class TrackEvent_Decoder : public ::protozero::TypedProtoDecoder { public: TrackEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {} explicit TrackEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast(raw.data()), raw.size()) {} explicit TrackEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {} bool has_category_iids() const { return at<3>().valid(); } ::protozero::RepeatedFieldIterator category_iids() const { return GetRepeated(3); } bool has_categories() const { return at<22>().valid(); } ::protozero::RepeatedFieldIterator<::protozero::ConstChars> categories() const { return GetRepeated<::protozero::ConstChars>(22); } bool has_name_iid() const { return at<10>().valid(); } uint64_t name_iid() const { return at<10>().as_uint64(); } bool has_name() const { return at<23>().valid(); } ::protozero::ConstChars name() const { return at<23>().as_string(); } bool has_type() const { return at<9>().valid(); } int32_t type() const { return at<9>().as_int32(); } bool has_track_uuid() const { return at<11>().valid(); } uint64_t track_uuid() const { return at<11>().as_uint64(); } bool has_counter_value() const { return at<30>().valid(); } int64_t counter_value() const { return at<30>().as_int64(); } bool has_double_counter_value() const { return at<44>().valid(); } double double_counter_value() const { return at<44>().as_double(); } bool has_extra_counter_track_uuids() const { return at<31>().valid(); } ::protozero::RepeatedFieldIterator extra_counter_track_uuids() const { return GetRepeated(31); } bool has_extra_counter_values() const { return at<12>().valid(); } ::protozero::RepeatedFieldIterator extra_counter_values() const { return GetRepeated(12); } bool has_extra_double_counter_track_uuids() const { return at<45>().valid(); } ::protozero::RepeatedFieldIterator extra_double_counter_track_uuids() const { return GetRepeated(45); } bool has_extra_double_counter_values() const { return at<46>().valid(); } ::protozero::RepeatedFieldIterator extra_double_counter_values() const { return GetRepeated(46); } bool has_flow_ids() const { return at<36>().valid(); } ::protozero::RepeatedFieldIterator flow_ids() const { return GetRepeated(36); } bool has_terminating_flow_ids() const { return at<42>().valid(); } ::protozero::RepeatedFieldIterator terminating_flow_ids() const { return GetRepeated(42); } bool has_debug_annotations() const { return at<4>().valid(); } ::protozero::RepeatedFieldIterator<::protozero::ConstBytes> debug_annotations() const { return GetRepeated<::protozero::ConstBytes>(4); } bool has_task_execution() const { return at<5>().valid(); } ::protozero::ConstBytes task_execution() const { return at<5>().as_bytes(); } bool has_log_message() const { return at<21>().valid(); } ::protozero::ConstBytes log_message() const { return at<21>().as_bytes(); } bool has_cc_scheduler_state() const { return at<24>().valid(); } ::protozero::ConstBytes cc_scheduler_state() const { return at<24>().as_bytes(); } bool has_chrome_user_event() const { return at<25>().valid(); } ::protozero::ConstBytes chrome_user_event() const { return at<25>().as_bytes(); } bool has_chrome_keyed_service() const { return at<26>().valid(); } ::protozero::ConstBytes chrome_keyed_service() const { return at<26>().as_bytes(); } bool has_chrome_legacy_ipc() const { return at<27>().valid(); } ::protozero::ConstBytes chrome_legacy_ipc() const { return at<27>().as_bytes(); } bool has_chrome_histogram_sample() const { return at<28>().valid(); } ::protozero::ConstBytes chrome_histogram_sample() const { return at<28>().as_bytes(); } bool has_chrome_latency_info() const { return at<29>().valid(); } ::protozero::ConstBytes chrome_latency_info() const { return at<29>().as_bytes(); } bool has_chrome_frame_reporter() const { return at<32>().valid(); } ::protozero::ConstBytes chrome_frame_reporter() const { return at<32>().as_bytes(); } bool has_chrome_application_state_info() const { return at<39>().valid(); } ::protozero::ConstBytes chrome_application_state_info() const { return at<39>().as_bytes(); } bool has_chrome_renderer_scheduler_state() const { return at<40>().valid(); } ::protozero::ConstBytes chrome_renderer_scheduler_state() const { return at<40>().as_bytes(); } bool has_chrome_window_handle_event_info() const { return at<41>().valid(); } ::protozero::ConstBytes chrome_window_handle_event_info() const { return at<41>().as_bytes(); } bool has_chrome_content_settings_event_info() const { return at<43>().valid(); } ::protozero::ConstBytes chrome_content_settings_event_info() const { return at<43>().as_bytes(); } bool has_source_location() const { return at<33>().valid(); } ::protozero::ConstBytes source_location() const { return at<33>().as_bytes(); } bool has_source_location_iid() const { return at<34>().valid(); } uint64_t source_location_iid() const { return at<34>().as_uint64(); } bool has_chrome_message_pump() const { return at<35>().valid(); } ::protozero::ConstBytes chrome_message_pump() const { return at<35>().as_bytes(); } bool has_chrome_mojo_event_info() const { return at<38>().valid(); } ::protozero::ConstBytes chrome_mojo_event_info() const { return at<38>().as_bytes(); } bool has_timestamp_delta_us() const { return at<1>().valid(); } int64_t timestamp_delta_us() const { return at<1>().as_int64(); } bool has_timestamp_absolute_us() const { return at<16>().valid(); } int64_t timestamp_absolute_us() const { return at<16>().as_int64(); } bool has_thread_time_delta_us() const { return at<2>().valid(); } int64_t thread_time_delta_us() const { return at<2>().as_int64(); } bool has_thread_time_absolute_us() const { return at<17>().valid(); } int64_t thread_time_absolute_us() const { return at<17>().as_int64(); } bool has_thread_instruction_count_delta() const { return at<8>().valid(); } int64_t thread_instruction_count_delta() const { return at<8>().as_int64(); } bool has_thread_instruction_count_absolute() const { return at<20>().valid(); } int64_t thread_instruction_count_absolute() const { return at<20>().as_int64(); } bool has_legacy_event() const { return at<6>().valid(); } ::protozero::ConstBytes legacy_event() const { return at<6>().as_bytes(); } }; class TrackEvent : public ::protozero::Message { public: using Decoder = TrackEvent_Decoder; enum : int32_t { kCategoryIidsFieldNumber = 3, kCategoriesFieldNumber = 22, kNameIidFieldNumber = 10, kNameFieldNumber = 23, kTypeFieldNumber = 9, kTrackUuidFieldNumber = 11, kCounterValueFieldNumber = 30, kDoubleCounterValueFieldNumber = 44, kExtraCounterTrackUuidsFieldNumber = 31, kExtraCounterValuesFieldNumber = 12, kExtraDoubleCounterTrackUuidsFieldNumber = 45, kExtraDoubleCounterValuesFieldNumber = 46, kFlowIdsFieldNumber = 36, kTerminatingFlowIdsFieldNumber = 42, kDebugAnnotationsFieldNumber = 4, kTaskExecutionFieldNumber = 5, kLogMessageFieldNumber = 21, kCcSchedulerStateFieldNumber = 24, kChromeUserEventFieldNumber = 25, kChromeKeyedServiceFieldNumber = 26, kChromeLegacyIpcFieldNumber = 27, kChromeHistogramSampleFieldNumber = 28, kChromeLatencyInfoFieldNumber = 29, kChromeFrameReporterFieldNumber = 32, kChromeApplicationStateInfoFieldNumber = 39, kChromeRendererSchedulerStateFieldNumber = 40, kChromeWindowHandleEventInfoFieldNumber = 41, kChromeContentSettingsEventInfoFieldNumber = 43, kSourceLocationFieldNumber = 33, kSourceLocationIidFieldNumber = 34, kChromeMessagePumpFieldNumber = 35, kChromeMojoEventInfoFieldNumber = 38, kTimestampDeltaUsFieldNumber = 1, kTimestampAbsoluteUsFieldNumber = 16, kThreadTimeDeltaUsFieldNumber = 2, kThreadTimeAbsoluteUsFieldNumber = 17, kThreadInstructionCountDeltaFieldNumber = 8, kThreadInstructionCountAbsoluteFieldNumber = 20, kLegacyEventFieldNumber = 6, }; using LegacyEvent = ::perfetto::protos::pbzero::TrackEvent_LegacyEvent; using Type = ::perfetto::protos::pbzero::TrackEvent_Type; static const Type TYPE_UNSPECIFIED = TrackEvent_Type_TYPE_UNSPECIFIED; static const Type TYPE_SLICE_BEGIN = TrackEvent_Type_TYPE_SLICE_BEGIN; static const Type TYPE_SLICE_END = TrackEvent_Type_TYPE_SLICE_END; static const Type TYPE_INSTANT = TrackEvent_Type_TYPE_INSTANT; static const Type TYPE_COUNTER = TrackEvent_Type_TYPE_COUNTER; using FieldMetadata_CategoryIids = ::protozero::proto_utils::FieldMetadata< 3, ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked, ::protozero::proto_utils::ProtoSchemaType::kUint64, uint64_t, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_CategoryIids kCategoryIids() { return {}; } void add_category_iids(uint64_t value) { static constexpr uint32_t field_id = FieldMetadata_CategoryIids::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kUint64> ::Append(*this, field_id, value); } using FieldMetadata_Categories = ::protozero::proto_utils::FieldMetadata< 22, ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked, ::protozero::proto_utils::ProtoSchemaType::kString, std::string, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_Categories kCategories() { return {}; } void add_categories(const char* data, size_t size) { AppendBytes(FieldMetadata_Categories::kFieldId, data, size); } void add_categories(std::string value) { static constexpr uint32_t field_id = FieldMetadata_Categories::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kString> ::Append(*this, field_id, value); } using FieldMetadata_NameIid = ::protozero::proto_utils::FieldMetadata< 10, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kUint64, uint64_t, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_NameIid kNameIid() { return {}; } void set_name_iid(uint64_t value) { static constexpr uint32_t field_id = FieldMetadata_NameIid::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kUint64> ::Append(*this, field_id, value); } using FieldMetadata_Name = ::protozero::proto_utils::FieldMetadata< 23, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kString, std::string, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_Name kName() { return {}; } void set_name(const char* data, size_t size) { AppendBytes(FieldMetadata_Name::kFieldId, data, size); } void set_name(std::string value) { static constexpr uint32_t field_id = FieldMetadata_Name::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kString> ::Append(*this, field_id, value); } using FieldMetadata_Type = ::protozero::proto_utils::FieldMetadata< 9, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kEnum, ::perfetto::protos::pbzero::TrackEvent_Type, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_Type kType() { return {}; } void set_type(::perfetto::protos::pbzero::TrackEvent_Type value) { static constexpr uint32_t field_id = FieldMetadata_Type::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kEnum> ::Append(*this, field_id, value); } using FieldMetadata_TrackUuid = ::protozero::proto_utils::FieldMetadata< 11, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kUint64, uint64_t, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_TrackUuid kTrackUuid() { return {}; } void set_track_uuid(uint64_t value) { static constexpr uint32_t field_id = FieldMetadata_TrackUuid::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kUint64> ::Append(*this, field_id, value); } using FieldMetadata_CounterValue = ::protozero::proto_utils::FieldMetadata< 30, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kInt64, int64_t, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_CounterValue kCounterValue() { return {}; } void set_counter_value(int64_t value) { static constexpr uint32_t field_id = FieldMetadata_CounterValue::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kInt64> ::Append(*this, field_id, value); } using FieldMetadata_DoubleCounterValue = ::protozero::proto_utils::FieldMetadata< 44, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kDouble, double, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_DoubleCounterValue kDoubleCounterValue() { return {}; } void set_double_counter_value(double value) { static constexpr uint32_t field_id = FieldMetadata_DoubleCounterValue::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kDouble> ::Append(*this, field_id, value); } using FieldMetadata_ExtraCounterTrackUuids = ::protozero::proto_utils::FieldMetadata< 31, ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked, ::protozero::proto_utils::ProtoSchemaType::kUint64, uint64_t, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ExtraCounterTrackUuids kExtraCounterTrackUuids() { return {}; } void add_extra_counter_track_uuids(uint64_t value) { static constexpr uint32_t field_id = FieldMetadata_ExtraCounterTrackUuids::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kUint64> ::Append(*this, field_id, value); } using FieldMetadata_ExtraCounterValues = ::protozero::proto_utils::FieldMetadata< 12, ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked, ::protozero::proto_utils::ProtoSchemaType::kInt64, int64_t, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ExtraCounterValues kExtraCounterValues() { return {}; } void add_extra_counter_values(int64_t value) { static constexpr uint32_t field_id = FieldMetadata_ExtraCounterValues::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kInt64> ::Append(*this, field_id, value); } using FieldMetadata_ExtraDoubleCounterTrackUuids = ::protozero::proto_utils::FieldMetadata< 45, ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked, ::protozero::proto_utils::ProtoSchemaType::kUint64, uint64_t, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ExtraDoubleCounterTrackUuids kExtraDoubleCounterTrackUuids() { return {}; } void add_extra_double_counter_track_uuids(uint64_t value) { static constexpr uint32_t field_id = FieldMetadata_ExtraDoubleCounterTrackUuids::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kUint64> ::Append(*this, field_id, value); } using FieldMetadata_ExtraDoubleCounterValues = ::protozero::proto_utils::FieldMetadata< 46, ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked, ::protozero::proto_utils::ProtoSchemaType::kDouble, double, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ExtraDoubleCounterValues kExtraDoubleCounterValues() { return {}; } void add_extra_double_counter_values(double value) { static constexpr uint32_t field_id = FieldMetadata_ExtraDoubleCounterValues::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kDouble> ::Append(*this, field_id, value); } using FieldMetadata_FlowIds = ::protozero::proto_utils::FieldMetadata< 36, ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked, ::protozero::proto_utils::ProtoSchemaType::kUint64, uint64_t, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_FlowIds kFlowIds() { return {}; } void add_flow_ids(uint64_t value) { static constexpr uint32_t field_id = FieldMetadata_FlowIds::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kUint64> ::Append(*this, field_id, value); } using FieldMetadata_TerminatingFlowIds = ::protozero::proto_utils::FieldMetadata< 42, ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked, ::protozero::proto_utils::ProtoSchemaType::kUint64, uint64_t, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_TerminatingFlowIds kTerminatingFlowIds() { return {}; } void add_terminating_flow_ids(uint64_t value) { static constexpr uint32_t field_id = FieldMetadata_TerminatingFlowIds::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kUint64> ::Append(*this, field_id, value); } using FieldMetadata_DebugAnnotations = ::protozero::proto_utils::FieldMetadata< 4, ::protozero::proto_utils::RepetitionType::kRepeatedNotPacked, ::protozero::proto_utils::ProtoSchemaType::kMessage, DebugAnnotation, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_DebugAnnotations kDebugAnnotations() { return {}; } template T* add_debug_annotations() { return BeginNestedMessage(4); } using FieldMetadata_TaskExecution = ::protozero::proto_utils::FieldMetadata< 5, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, TaskExecution, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_TaskExecution kTaskExecution() { return {}; } template T* set_task_execution() { return BeginNestedMessage(5); } using FieldMetadata_LogMessage = ::protozero::proto_utils::FieldMetadata< 21, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, LogMessage, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_LogMessage kLogMessage() { return {}; } template T* set_log_message() { return BeginNestedMessage(21); } using FieldMetadata_CcSchedulerState = ::protozero::proto_utils::FieldMetadata< 24, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, ChromeCompositorSchedulerState, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_CcSchedulerState kCcSchedulerState() { return {}; } template T* set_cc_scheduler_state() { return BeginNestedMessage(24); } using FieldMetadata_ChromeUserEvent = ::protozero::proto_utils::FieldMetadata< 25, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, ChromeUserEvent, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ChromeUserEvent kChromeUserEvent() { return {}; } template T* set_chrome_user_event() { return BeginNestedMessage(25); } using FieldMetadata_ChromeKeyedService = ::protozero::proto_utils::FieldMetadata< 26, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, ChromeKeyedService, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ChromeKeyedService kChromeKeyedService() { return {}; } template T* set_chrome_keyed_service() { return BeginNestedMessage(26); } using FieldMetadata_ChromeLegacyIpc = ::protozero::proto_utils::FieldMetadata< 27, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, ChromeLegacyIpc, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ChromeLegacyIpc kChromeLegacyIpc() { return {}; } template T* set_chrome_legacy_ipc() { return BeginNestedMessage(27); } using FieldMetadata_ChromeHistogramSample = ::protozero::proto_utils::FieldMetadata< 28, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, ChromeHistogramSample, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ChromeHistogramSample kChromeHistogramSample() { return {}; } template T* set_chrome_histogram_sample() { return BeginNestedMessage(28); } using FieldMetadata_ChromeLatencyInfo = ::protozero::proto_utils::FieldMetadata< 29, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, ChromeLatencyInfo, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ChromeLatencyInfo kChromeLatencyInfo() { return {}; } template T* set_chrome_latency_info() { return BeginNestedMessage(29); } using FieldMetadata_ChromeFrameReporter = ::protozero::proto_utils::FieldMetadata< 32, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, ChromeFrameReporter, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ChromeFrameReporter kChromeFrameReporter() { return {}; } template T* set_chrome_frame_reporter() { return BeginNestedMessage(32); } using FieldMetadata_ChromeApplicationStateInfo = ::protozero::proto_utils::FieldMetadata< 39, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, ChromeApplicationStateInfo, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ChromeApplicationStateInfo kChromeApplicationStateInfo() { return {}; } template T* set_chrome_application_state_info() { return BeginNestedMessage(39); } using FieldMetadata_ChromeRendererSchedulerState = ::protozero::proto_utils::FieldMetadata< 40, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, ChromeRendererSchedulerState, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ChromeRendererSchedulerState kChromeRendererSchedulerState() { return {}; } template T* set_chrome_renderer_scheduler_state() { return BeginNestedMessage(40); } using FieldMetadata_ChromeWindowHandleEventInfo = ::protozero::proto_utils::FieldMetadata< 41, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, ChromeWindowHandleEventInfo, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ChromeWindowHandleEventInfo kChromeWindowHandleEventInfo() { return {}; } template T* set_chrome_window_handle_event_info() { return BeginNestedMessage(41); } using FieldMetadata_ChromeContentSettingsEventInfo = ::protozero::proto_utils::FieldMetadata< 43, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, ChromeContentSettingsEventInfo, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ChromeContentSettingsEventInfo kChromeContentSettingsEventInfo() { return {}; } template T* set_chrome_content_settings_event_info() { return BeginNestedMessage(43); } using FieldMetadata_SourceLocation = ::protozero::proto_utils::FieldMetadata< 33, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, SourceLocation, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_SourceLocation kSourceLocation() { return {}; } template T* set_source_location() { return BeginNestedMessage(33); } using FieldMetadata_SourceLocationIid = ::protozero::proto_utils::FieldMetadata< 34, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kUint64, uint64_t, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_SourceLocationIid kSourceLocationIid() { return {}; } void set_source_location_iid(uint64_t value) { static constexpr uint32_t field_id = FieldMetadata_SourceLocationIid::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kUint64> ::Append(*this, field_id, value); } using FieldMetadata_ChromeMessagePump = ::protozero::proto_utils::FieldMetadata< 35, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, ChromeMessagePump, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ChromeMessagePump kChromeMessagePump() { return {}; } template T* set_chrome_message_pump() { return BeginNestedMessage(35); } using FieldMetadata_ChromeMojoEventInfo = ::protozero::proto_utils::FieldMetadata< 38, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, ChromeMojoEventInfo, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ChromeMojoEventInfo kChromeMojoEventInfo() { return {}; } template T* set_chrome_mojo_event_info() { return BeginNestedMessage(38); } using FieldMetadata_TimestampDeltaUs = ::protozero::proto_utils::FieldMetadata< 1, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kInt64, int64_t, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_TimestampDeltaUs kTimestampDeltaUs() { return {}; } void set_timestamp_delta_us(int64_t value) { static constexpr uint32_t field_id = FieldMetadata_TimestampDeltaUs::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kInt64> ::Append(*this, field_id, value); } using FieldMetadata_TimestampAbsoluteUs = ::protozero::proto_utils::FieldMetadata< 16, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kInt64, int64_t, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_TimestampAbsoluteUs kTimestampAbsoluteUs() { return {}; } void set_timestamp_absolute_us(int64_t value) { static constexpr uint32_t field_id = FieldMetadata_TimestampAbsoluteUs::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kInt64> ::Append(*this, field_id, value); } using FieldMetadata_ThreadTimeDeltaUs = ::protozero::proto_utils::FieldMetadata< 2, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kInt64, int64_t, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ThreadTimeDeltaUs kThreadTimeDeltaUs() { return {}; } void set_thread_time_delta_us(int64_t value) { static constexpr uint32_t field_id = FieldMetadata_ThreadTimeDeltaUs::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kInt64> ::Append(*this, field_id, value); } using FieldMetadata_ThreadTimeAbsoluteUs = ::protozero::proto_utils::FieldMetadata< 17, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kInt64, int64_t, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ThreadTimeAbsoluteUs kThreadTimeAbsoluteUs() { return {}; } void set_thread_time_absolute_us(int64_t value) { static constexpr uint32_t field_id = FieldMetadata_ThreadTimeAbsoluteUs::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kInt64> ::Append(*this, field_id, value); } using FieldMetadata_ThreadInstructionCountDelta = ::protozero::proto_utils::FieldMetadata< 8, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kInt64, int64_t, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ThreadInstructionCountDelta kThreadInstructionCountDelta() { return {}; } void set_thread_instruction_count_delta(int64_t value) { static constexpr uint32_t field_id = FieldMetadata_ThreadInstructionCountDelta::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kInt64> ::Append(*this, field_id, value); } using FieldMetadata_ThreadInstructionCountAbsolute = ::protozero::proto_utils::FieldMetadata< 20, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kInt64, int64_t, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ThreadInstructionCountAbsolute kThreadInstructionCountAbsolute() { return {}; } void set_thread_instruction_count_absolute(int64_t value) { static constexpr uint32_t field_id = FieldMetadata_ThreadInstructionCountAbsolute::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kInt64> ::Append(*this, field_id, value); } using FieldMetadata_LegacyEvent = ::protozero::proto_utils::FieldMetadata< 6, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, TrackEvent_LegacyEvent, TrackEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_LegacyEvent kLegacyEvent() { return {}; } template T* set_legacy_event() { return BeginNestedMessage(6); } }; class TrackEvent_LegacyEvent_Decoder : public ::protozero::TypedProtoDecoder { public: TrackEvent_LegacyEvent_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {} explicit TrackEvent_LegacyEvent_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast(raw.data()), raw.size()) {} explicit TrackEvent_LegacyEvent_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {} bool has_name_iid() const { return at<1>().valid(); } uint64_t name_iid() const { return at<1>().as_uint64(); } bool has_phase() const { return at<2>().valid(); } int32_t phase() const { return at<2>().as_int32(); } bool has_duration_us() const { return at<3>().valid(); } int64_t duration_us() const { return at<3>().as_int64(); } bool has_thread_duration_us() const { return at<4>().valid(); } int64_t thread_duration_us() const { return at<4>().as_int64(); } bool has_thread_instruction_delta() const { return at<15>().valid(); } int64_t thread_instruction_delta() const { return at<15>().as_int64(); } bool has_unscoped_id() const { return at<6>().valid(); } uint64_t unscoped_id() const { return at<6>().as_uint64(); } bool has_local_id() const { return at<10>().valid(); } uint64_t local_id() const { return at<10>().as_uint64(); } bool has_global_id() const { return at<11>().valid(); } uint64_t global_id() const { return at<11>().as_uint64(); } bool has_id_scope() const { return at<7>().valid(); } ::protozero::ConstChars id_scope() const { return at<7>().as_string(); } bool has_use_async_tts() const { return at<9>().valid(); } bool use_async_tts() const { return at<9>().as_bool(); } bool has_bind_id() const { return at<8>().valid(); } uint64_t bind_id() const { return at<8>().as_uint64(); } bool has_bind_to_enclosing() const { return at<12>().valid(); } bool bind_to_enclosing() const { return at<12>().as_bool(); } bool has_flow_direction() const { return at<13>().valid(); } int32_t flow_direction() const { return at<13>().as_int32(); } bool has_instant_event_scope() const { return at<14>().valid(); } int32_t instant_event_scope() const { return at<14>().as_int32(); } bool has_pid_override() const { return at<18>().valid(); } int32_t pid_override() const { return at<18>().as_int32(); } bool has_tid_override() const { return at<19>().valid(); } int32_t tid_override() const { return at<19>().as_int32(); } }; class TrackEvent_LegacyEvent : public ::protozero::Message { public: using Decoder = TrackEvent_LegacyEvent_Decoder; enum : int32_t { kNameIidFieldNumber = 1, kPhaseFieldNumber = 2, kDurationUsFieldNumber = 3, kThreadDurationUsFieldNumber = 4, kThreadInstructionDeltaFieldNumber = 15, kUnscopedIdFieldNumber = 6, kLocalIdFieldNumber = 10, kGlobalIdFieldNumber = 11, kIdScopeFieldNumber = 7, kUseAsyncTtsFieldNumber = 9, kBindIdFieldNumber = 8, kBindToEnclosingFieldNumber = 12, kFlowDirectionFieldNumber = 13, kInstantEventScopeFieldNumber = 14, kPidOverrideFieldNumber = 18, kTidOverrideFieldNumber = 19, }; using FlowDirection = ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_FlowDirection; using InstantEventScope = ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_InstantEventScope; static const FlowDirection FLOW_UNSPECIFIED = TrackEvent_LegacyEvent_FlowDirection_FLOW_UNSPECIFIED; static const FlowDirection FLOW_IN = TrackEvent_LegacyEvent_FlowDirection_FLOW_IN; static const FlowDirection FLOW_OUT = TrackEvent_LegacyEvent_FlowDirection_FLOW_OUT; static const FlowDirection FLOW_INOUT = TrackEvent_LegacyEvent_FlowDirection_FLOW_INOUT; static const InstantEventScope SCOPE_UNSPECIFIED = TrackEvent_LegacyEvent_InstantEventScope_SCOPE_UNSPECIFIED; static const InstantEventScope SCOPE_GLOBAL = TrackEvent_LegacyEvent_InstantEventScope_SCOPE_GLOBAL; static const InstantEventScope SCOPE_PROCESS = TrackEvent_LegacyEvent_InstantEventScope_SCOPE_PROCESS; static const InstantEventScope SCOPE_THREAD = TrackEvent_LegacyEvent_InstantEventScope_SCOPE_THREAD; using FieldMetadata_NameIid = ::protozero::proto_utils::FieldMetadata< 1, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kUint64, uint64_t, TrackEvent_LegacyEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_NameIid kNameIid() { return {}; } void set_name_iid(uint64_t value) { static constexpr uint32_t field_id = FieldMetadata_NameIid::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kUint64> ::Append(*this, field_id, value); } using FieldMetadata_Phase = ::protozero::proto_utils::FieldMetadata< 2, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kInt32, int32_t, TrackEvent_LegacyEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_Phase kPhase() { return {}; } void set_phase(int32_t value) { static constexpr uint32_t field_id = FieldMetadata_Phase::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kInt32> ::Append(*this, field_id, value); } using FieldMetadata_DurationUs = ::protozero::proto_utils::FieldMetadata< 3, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kInt64, int64_t, TrackEvent_LegacyEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_DurationUs kDurationUs() { return {}; } void set_duration_us(int64_t value) { static constexpr uint32_t field_id = FieldMetadata_DurationUs::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kInt64> ::Append(*this, field_id, value); } using FieldMetadata_ThreadDurationUs = ::protozero::proto_utils::FieldMetadata< 4, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kInt64, int64_t, TrackEvent_LegacyEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ThreadDurationUs kThreadDurationUs() { return {}; } void set_thread_duration_us(int64_t value) { static constexpr uint32_t field_id = FieldMetadata_ThreadDurationUs::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kInt64> ::Append(*this, field_id, value); } using FieldMetadata_ThreadInstructionDelta = ::protozero::proto_utils::FieldMetadata< 15, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kInt64, int64_t, TrackEvent_LegacyEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ThreadInstructionDelta kThreadInstructionDelta() { return {}; } void set_thread_instruction_delta(int64_t value) { static constexpr uint32_t field_id = FieldMetadata_ThreadInstructionDelta::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kInt64> ::Append(*this, field_id, value); } using FieldMetadata_UnscopedId = ::protozero::proto_utils::FieldMetadata< 6, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kUint64, uint64_t, TrackEvent_LegacyEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_UnscopedId kUnscopedId() { return {}; } void set_unscoped_id(uint64_t value) { static constexpr uint32_t field_id = FieldMetadata_UnscopedId::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kUint64> ::Append(*this, field_id, value); } using FieldMetadata_LocalId = ::protozero::proto_utils::FieldMetadata< 10, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kUint64, uint64_t, TrackEvent_LegacyEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_LocalId kLocalId() { return {}; } void set_local_id(uint64_t value) { static constexpr uint32_t field_id = FieldMetadata_LocalId::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kUint64> ::Append(*this, field_id, value); } using FieldMetadata_GlobalId = ::protozero::proto_utils::FieldMetadata< 11, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kUint64, uint64_t, TrackEvent_LegacyEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_GlobalId kGlobalId() { return {}; } void set_global_id(uint64_t value) { static constexpr uint32_t field_id = FieldMetadata_GlobalId::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kUint64> ::Append(*this, field_id, value); } using FieldMetadata_IdScope = ::protozero::proto_utils::FieldMetadata< 7, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kString, std::string, TrackEvent_LegacyEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_IdScope kIdScope() { return {}; } void set_id_scope(const char* data, size_t size) { AppendBytes(FieldMetadata_IdScope::kFieldId, data, size); } void set_id_scope(std::string value) { static constexpr uint32_t field_id = FieldMetadata_IdScope::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kString> ::Append(*this, field_id, value); } using FieldMetadata_UseAsyncTts = ::protozero::proto_utils::FieldMetadata< 9, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kBool, bool, TrackEvent_LegacyEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_UseAsyncTts kUseAsyncTts() { return {}; } void set_use_async_tts(bool value) { static constexpr uint32_t field_id = FieldMetadata_UseAsyncTts::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kBool> ::Append(*this, field_id, value); } using FieldMetadata_BindId = ::protozero::proto_utils::FieldMetadata< 8, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kUint64, uint64_t, TrackEvent_LegacyEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_BindId kBindId() { return {}; } void set_bind_id(uint64_t value) { static constexpr uint32_t field_id = FieldMetadata_BindId::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kUint64> ::Append(*this, field_id, value); } using FieldMetadata_BindToEnclosing = ::protozero::proto_utils::FieldMetadata< 12, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kBool, bool, TrackEvent_LegacyEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_BindToEnclosing kBindToEnclosing() { return {}; } void set_bind_to_enclosing(bool value) { static constexpr uint32_t field_id = FieldMetadata_BindToEnclosing::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kBool> ::Append(*this, field_id, value); } using FieldMetadata_FlowDirection = ::protozero::proto_utils::FieldMetadata< 13, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kEnum, ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_FlowDirection, TrackEvent_LegacyEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_FlowDirection kFlowDirection() { return {}; } void set_flow_direction(::perfetto::protos::pbzero::TrackEvent_LegacyEvent_FlowDirection value) { static constexpr uint32_t field_id = FieldMetadata_FlowDirection::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kEnum> ::Append(*this, field_id, value); } using FieldMetadata_InstantEventScope = ::protozero::proto_utils::FieldMetadata< 14, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kEnum, ::perfetto::protos::pbzero::TrackEvent_LegacyEvent_InstantEventScope, TrackEvent_LegacyEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_InstantEventScope kInstantEventScope() { return {}; } void set_instant_event_scope(::perfetto::protos::pbzero::TrackEvent_LegacyEvent_InstantEventScope value) { static constexpr uint32_t field_id = FieldMetadata_InstantEventScope::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kEnum> ::Append(*this, field_id, value); } using FieldMetadata_PidOverride = ::protozero::proto_utils::FieldMetadata< 18, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kInt32, int32_t, TrackEvent_LegacyEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_PidOverride kPidOverride() { return {}; } void set_pid_override(int32_t value) { static constexpr uint32_t field_id = FieldMetadata_PidOverride::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kInt32> ::Append(*this, field_id, value); } using FieldMetadata_TidOverride = ::protozero::proto_utils::FieldMetadata< 19, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kInt32, int32_t, TrackEvent_LegacyEvent>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_TidOverride kTidOverride() { return {}; } void set_tid_override(int32_t value) { static constexpr uint32_t field_id = FieldMetadata_TidOverride::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kInt32> ::Append(*this, field_id, value); } }; } // Namespace. } // Namespace. } // Namespace. #endif // Include guard. /* * Copyright (C) 2020 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_TRACING_TRACK_EVENT_STATE_TRACKER_H_ #define INCLUDE_PERFETTO_TRACING_TRACK_EVENT_STATE_TRACKER_H_ // gen_amalgamated expanded: #include "perfetto/base/export.h" // gen_amalgamated expanded: #include "protos/perfetto/trace/track_event/track_event.pbzero.h" #include #include #include namespace perfetto { namespace protos { namespace pbzero { class TracePacket_Decoder; class TrackEvent; class TrackEvent_Decoder; } // namespace pbzero } // namespace protos // A helper for keeping track of incremental state when intercepting track // events. class PERFETTO_EXPORT TrackEventStateTracker { public: ~TrackEventStateTracker(); struct StackFrame { uint64_t timestamp{}; // Only one of |name| and |name_iid| will be set. std::string name; uint64_t name_iid{}; uint64_t name_hash{}; // Only one of |category| and |category_iid| will be set. std::string category; uint64_t category_iid{}; }; struct Track { uint64_t uuid{}; uint32_t index{}; // Ordinal number for the track in the tracing session. std::string name; int64_t pid{}; int64_t tid{}; // Opaque user data associated with the track. std::vector user_data; // Stack of opened slices on this track. std::vector stack; }; // State for a single trace writer sequence (typically a single thread). struct SequenceState { // Trace packet sequence defaults. Track track; // Interned state. #if PERFETTO_DCHECK_IS_ON() uint32_t sequence_id{}; #endif std::map event_names; std::map event_categories; std::map debug_annotation_names; }; // State for the entire tracing session. Shared by all trace writer sequences // participating in the session. struct SessionState { // Non-thread-bound tracks. std::map tracks; }; // Represents a single decoded track event (without arguments). struct ParsedTrackEvent { explicit ParsedTrackEvent( const perfetto::protos::pbzero::TrackEvent::Decoder&); // Underlying event. const perfetto::protos::pbzero::TrackEvent::Decoder& track_event; // Event metadata. uint64_t timestamp_ns{}; uint64_t duration_ns{}; size_t stack_depth{}; protozero::ConstChars category{}; protozero::ConstChars name{}; uint64_t name_hash{}; }; // Interface used by the tracker to access tracing session and sequence state // and to report parsed track events. class Delegate { public: virtual ~Delegate(); // Called to retrieve the session-global state shared by all sequences. The // returned pointer must remain valid (locked) throughout the call to // |ProcessTracePacket|. virtual SessionState* GetSessionState() = 0; // Called when the metadata (e.g., name) for a track changes. |Track| can be // modified by the callback to attach user data. virtual void OnTrackUpdated(Track&) = 0; // If the packet given to |ProcessTracePacket| contains a track event, this // method is called to report the properties of that event. Note that memory // pointers in |TrackEvent| will only be valid during this call. virtual void OnTrackEvent(const Track&, const ParsedTrackEvent&) = 0; }; // Process a single trace packet, reporting any contained track event back via // the delegate interface. |SequenceState| must correspond to the sequence // that was used to write the packet. static void ProcessTracePacket(Delegate&, SequenceState&, const protos::pbzero::TracePacket_Decoder&); private: static void UpdateIncrementalState( Delegate&, SequenceState&, const protos::pbzero::TracePacket_Decoder&); }; } // namespace perfetto #endif // INCLUDE_PERFETTO_TRACING_TRACK_EVENT_STATE_TRACKER_H_ /* * Copyright (C) 2020 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_TRACING_CONSOLE_INTERCEPTOR_H_ #define INCLUDE_PERFETTO_TRACING_CONSOLE_INTERCEPTOR_H_ // gen_amalgamated expanded: #include "perfetto/base/compiler.h" // gen_amalgamated expanded: #include "perfetto/base/logging.h" // gen_amalgamated expanded: #include "perfetto/tracing/interceptor.h" // gen_amalgamated expanded: #include "perfetto/tracing/track_event_state_tracker.h" #include #include #include #include #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) #include #else #include #endif #if defined(__GNUC__) || defined(__clang__) #define PERFETTO_PRINTF_ATTR \ __attribute__((format(printf, /*format_index=*/2, /*first_to_check=*/3))) #else #define PERFETTO_PRINTF_ATTR #endif #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && !defined(STDOUT_FILENO) #define STDOUT_FILENO 1 #define STDERR_FILENO 2 #endif namespace perfetto { namespace protos { namespace pbzero { class DebugAnnotation_Decoder; class TracePacket_Decoder; class TrackEvent_Decoder; } // namespace pbzero } // namespace protos struct ConsoleColor; class PERFETTO_EXPORT ConsoleInterceptor : public Interceptor { public: ~ConsoleInterceptor() override; static void Register(); static void OnTracePacket(InterceptorContext context); static void SetOutputFdForTesting(int fd); void OnSetup(const SetupArgs&) override; void OnStart(const StartArgs&) override; void OnStop(const StopArgs&) override; struct ThreadLocalState : public InterceptorBase::ThreadLocalState { ThreadLocalState(ThreadLocalStateArgs&); ~ThreadLocalState() override; // Destination file. Assumed to stay valid until the program ends (i.e., is // stderr or stdout). int fd{}; bool use_colors{}; // Messages up to this length are buffered and written atomically. If a // message is longer, it will be printed with multiple writes. std::array message_buffer{}; size_t buffer_pos{}; // We only support a single trace writer sequence per thread, so the // sequence state is stored in TLS. TrackEventStateTracker::SequenceState sequence_state; uint64_t start_time_ns{}; }; private: class Delegate; // Appends a formatted message to |message_buffer_| or directly to the output // file if the buffer is full. static void Printf(InterceptorContext& context, const char* format, ...) PERFETTO_PRINTF_ATTR; static void Flush(InterceptorContext& context); static void SetColor(InterceptorContext& context, const ConsoleColor&); static void SetColor(InterceptorContext& context, const char*); static void PrintDebugAnnotations(InterceptorContext&, const protos::pbzero::TrackEvent_Decoder&, const ConsoleColor& slice_color, const ConsoleColor& highlight_color); static void PrintDebugAnnotationName( InterceptorContext&, const perfetto::protos::pbzero::DebugAnnotation_Decoder& annotation); static void PrintDebugAnnotationValue( InterceptorContext&, const perfetto::protos::pbzero::DebugAnnotation_Decoder& annotation); int fd_ = STDOUT_FILENO; bool use_colors_ = true; TrackEventStateTracker::SessionState session_state_; uint64_t start_time_ns_{}; }; } // namespace perfetto #endif // INCLUDE_PERFETTO_TRACING_CONSOLE_INTERCEPTOR_H_ // gen_amalgamated begin header: include/perfetto/tracing/core/data_source_config.h // gen_amalgamated begin header: gen/protos/perfetto/config/data_source_config.gen.h // gen_amalgamated begin header: include/perfetto/protozero/cpp_message_obj.h /* * Copyright (C) 2019 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_PROTOZERO_CPP_MESSAGE_OBJ_H_ #define INCLUDE_PERFETTO_PROTOZERO_CPP_MESSAGE_OBJ_H_ #include #include #include // gen_amalgamated expanded: #include "perfetto/base/export.h" namespace protozero { // Base class for generated .gen.h classes, which are full C++ objects that // support both ser and deserialization (but are not zero-copy). // This is only used by the "cpp" targets not the "pbzero" ones. class PERFETTO_EXPORT CppMessageObj { public: virtual ~CppMessageObj(); virtual std::string SerializeAsString() const = 0; virtual std::vector SerializeAsArray() const = 0; virtual bool ParseFromArray(const void*, size_t) = 0; bool ParseFromString(const std::string& str) { return ParseFromArray(str.data(), str.size()); } }; } // namespace protozero #endif // INCLUDE_PERFETTO_PROTOZERO_CPP_MESSAGE_OBJ_H_ // gen_amalgamated begin header: include/perfetto/protozero/copyable_ptr.h /* * Copyright (C) 2019 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_PROTOZERO_COPYABLE_PTR_H_ #define INCLUDE_PERFETTO_PROTOZERO_COPYABLE_PTR_H_ #include namespace protozero { // This class is essentially a std::vector of fixed size = 1. // It's a pointer wrapper with deep copying and deep equality comparison. // At all effects this wrapper behaves like the underlying T, with the exception // of the heap indirection. // Conversely to a std::unique_ptr, the pointer will be always valid, never // null. The problem it solves is the following: when generating C++ classes // from proto files, we want to keep each header hermetic (i.e. not #include // headers of dependent types). As such we can't directly instantiate T // field members but we can instead rely on pointers, so only the .cc file needs // to see the actual definition of T. If the generated classes were move-only we // could just use a unique_ptr there. But they aren't, hence this wrapper. // Converesely to unique_ptr, this wrapper: // - Default constructs the T instance in its constructor. // - Implements deep comparison in operator== instead of pointer comparison. template class CopyablePtr { public: CopyablePtr() : ptr_(new T()) {} ~CopyablePtr() = default; // Copy operators. CopyablePtr(const CopyablePtr& other) : ptr_(new T(*other.ptr_)) {} CopyablePtr& operator=(const CopyablePtr& other) { *ptr_ = *other.ptr_; return *this; } // Move operators. CopyablePtr(CopyablePtr&& other) noexcept : ptr_(std::move(other.ptr_)) { other.ptr_.reset(new T()); } CopyablePtr& operator=(CopyablePtr&& other) { ptr_ = std::move(other.ptr_); other.ptr_.reset(new T()); return *this; } T* get() { return ptr_.get(); } const T* get() const { return ptr_.get(); } T* operator->() { return ptr_.get(); } const T* operator->() const { return ptr_.get(); } T& operator*() { return *ptr_; } const T& operator*() const { return *ptr_; } friend bool operator==(const CopyablePtr& lhs, const CopyablePtr& rhs) { return *lhs == *rhs; } friend bool operator!=(const CopyablePtr& lhs, const CopyablePtr& rhs) { // In theory the underlying type might have a special operator!= // implementation which is not just !(x == y). Respect that. return *lhs != *rhs; } private: std::unique_ptr ptr_; }; } // namespace protozero #endif // INCLUDE_PERFETTO_PROTOZERO_COPYABLE_PTR_H_ // DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin #ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_DATA_SOURCE_CONFIG_PROTO_CPP_H_ #define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_DATA_SOURCE_CONFIG_PROTO_CPP_H_ #include #include #include #include #include // gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h" // gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h" // gen_amalgamated expanded: #include "perfetto/base/export.h" namespace perfetto { namespace protos { namespace gen { class DataSourceConfig; class TestConfig; class TestConfig_DummyFields; class InterceptorConfig; class ChromeConfig; enum DataSourceConfig_SessionInitiator : int; enum ChromeConfig_ClientPriority : int; } // namespace perfetto } // namespace protos } // namespace gen namespace protozero { class Message; } // namespace protozero namespace perfetto { namespace protos { namespace gen { enum DataSourceConfig_SessionInitiator : int { DataSourceConfig_SessionInitiator_SESSION_INITIATOR_UNSPECIFIED = 0, DataSourceConfig_SessionInitiator_SESSION_INITIATOR_TRUSTED_SYSTEM = 1, }; class PERFETTO_EXPORT DataSourceConfig : public ::protozero::CppMessageObj { public: using SessionInitiator = DataSourceConfig_SessionInitiator; static constexpr auto SESSION_INITIATOR_UNSPECIFIED = DataSourceConfig_SessionInitiator_SESSION_INITIATOR_UNSPECIFIED; static constexpr auto SESSION_INITIATOR_TRUSTED_SYSTEM = DataSourceConfig_SessionInitiator_SESSION_INITIATOR_TRUSTED_SYSTEM; static constexpr auto SessionInitiator_MIN = DataSourceConfig_SessionInitiator_SESSION_INITIATOR_UNSPECIFIED; static constexpr auto SessionInitiator_MAX = DataSourceConfig_SessionInitiator_SESSION_INITIATOR_TRUSTED_SYSTEM; enum FieldNumbers { kNameFieldNumber = 1, kTargetBufferFieldNumber = 2, kTraceDurationMsFieldNumber = 3, kStopTimeoutMsFieldNumber = 7, kEnableExtraGuardrailsFieldNumber = 6, kSessionInitiatorFieldNumber = 8, kTracingSessionIdFieldNumber = 4, kFtraceConfigFieldNumber = 100, kInodeFileConfigFieldNumber = 102, kProcessStatsConfigFieldNumber = 103, kSysStatsConfigFieldNumber = 104, kHeapprofdConfigFieldNumber = 105, kJavaHprofConfigFieldNumber = 110, kAndroidPowerConfigFieldNumber = 106, kAndroidLogConfigFieldNumber = 107, kGpuCounterConfigFieldNumber = 108, kPackagesListConfigFieldNumber = 109, kPerfEventConfigFieldNumber = 111, kVulkanMemoryConfigFieldNumber = 112, kTrackEventConfigFieldNumber = 113, kAndroidPolledStateConfigFieldNumber = 114, kChromeConfigFieldNumber = 101, kInterceptorConfigFieldNumber = 115, kLegacyConfigFieldNumber = 1000, kForTestingFieldNumber = 1001, }; DataSourceConfig(); ~DataSourceConfig() override; DataSourceConfig(DataSourceConfig&&) noexcept; DataSourceConfig& operator=(DataSourceConfig&&); DataSourceConfig(const DataSourceConfig&); DataSourceConfig& operator=(const DataSourceConfig&); bool operator==(const DataSourceConfig&) const; bool operator!=(const DataSourceConfig& other) const { return !(*this == other); } bool ParseFromArray(const void*, size_t) override; std::string SerializeAsString() const override; std::vector SerializeAsArray() const override; void Serialize(::protozero::Message*) const; bool has_name() const { return _has_field_[1]; } const std::string& name() const { return name_; } void set_name(const std::string& value) { name_ = value; _has_field_.set(1); } bool has_target_buffer() const { return _has_field_[2]; } uint32_t target_buffer() const { return target_buffer_; } void set_target_buffer(uint32_t value) { target_buffer_ = value; _has_field_.set(2); } bool has_trace_duration_ms() const { return _has_field_[3]; } uint32_t trace_duration_ms() const { return trace_duration_ms_; } void set_trace_duration_ms(uint32_t value) { trace_duration_ms_ = value; _has_field_.set(3); } bool has_stop_timeout_ms() const { return _has_field_[7]; } uint32_t stop_timeout_ms() const { return stop_timeout_ms_; } void set_stop_timeout_ms(uint32_t value) { stop_timeout_ms_ = value; _has_field_.set(7); } bool has_enable_extra_guardrails() const { return _has_field_[6]; } bool enable_extra_guardrails() const { return enable_extra_guardrails_; } void set_enable_extra_guardrails(bool value) { enable_extra_guardrails_ = value; _has_field_.set(6); } bool has_session_initiator() const { return _has_field_[8]; } DataSourceConfig_SessionInitiator session_initiator() const { return session_initiator_; } void set_session_initiator(DataSourceConfig_SessionInitiator value) { session_initiator_ = value; _has_field_.set(8); } bool has_tracing_session_id() const { return _has_field_[4]; } uint64_t tracing_session_id() const { return tracing_session_id_; } void set_tracing_session_id(uint64_t value) { tracing_session_id_ = value; _has_field_.set(4); } const std::string& ftrace_config_raw() const { return ftrace_config_; } void set_ftrace_config_raw(const std::string& raw) { ftrace_config_ = raw; _has_field_.set(100); } const std::string& inode_file_config_raw() const { return inode_file_config_; } void set_inode_file_config_raw(const std::string& raw) { inode_file_config_ = raw; _has_field_.set(102); } const std::string& process_stats_config_raw() const { return process_stats_config_; } void set_process_stats_config_raw(const std::string& raw) { process_stats_config_ = raw; _has_field_.set(103); } const std::string& sys_stats_config_raw() const { return sys_stats_config_; } void set_sys_stats_config_raw(const std::string& raw) { sys_stats_config_ = raw; _has_field_.set(104); } const std::string& heapprofd_config_raw() const { return heapprofd_config_; } void set_heapprofd_config_raw(const std::string& raw) { heapprofd_config_ = raw; _has_field_.set(105); } const std::string& java_hprof_config_raw() const { return java_hprof_config_; } void set_java_hprof_config_raw(const std::string& raw) { java_hprof_config_ = raw; _has_field_.set(110); } const std::string& android_power_config_raw() const { return android_power_config_; } void set_android_power_config_raw(const std::string& raw) { android_power_config_ = raw; _has_field_.set(106); } const std::string& android_log_config_raw() const { return android_log_config_; } void set_android_log_config_raw(const std::string& raw) { android_log_config_ = raw; _has_field_.set(107); } const std::string& gpu_counter_config_raw() const { return gpu_counter_config_; } void set_gpu_counter_config_raw(const std::string& raw) { gpu_counter_config_ = raw; _has_field_.set(108); } const std::string& packages_list_config_raw() const { return packages_list_config_; } void set_packages_list_config_raw(const std::string& raw) { packages_list_config_ = raw; _has_field_.set(109); } const std::string& perf_event_config_raw() const { return perf_event_config_; } void set_perf_event_config_raw(const std::string& raw) { perf_event_config_ = raw; _has_field_.set(111); } const std::string& vulkan_memory_config_raw() const { return vulkan_memory_config_; } void set_vulkan_memory_config_raw(const std::string& raw) { vulkan_memory_config_ = raw; _has_field_.set(112); } const std::string& track_event_config_raw() const { return track_event_config_; } void set_track_event_config_raw(const std::string& raw) { track_event_config_ = raw; _has_field_.set(113); } const std::string& android_polled_state_config_raw() const { return android_polled_state_config_; } void set_android_polled_state_config_raw(const std::string& raw) { android_polled_state_config_ = raw; _has_field_.set(114); } bool has_chrome_config() const { return _has_field_[101]; } const ChromeConfig& chrome_config() const { return *chrome_config_; } ChromeConfig* mutable_chrome_config() { _has_field_.set(101); return chrome_config_.get(); } bool has_interceptor_config() const { return _has_field_[115]; } const InterceptorConfig& interceptor_config() const { return *interceptor_config_; } InterceptorConfig* mutable_interceptor_config() { _has_field_.set(115); return interceptor_config_.get(); } bool has_legacy_config() const { return _has_field_[1000]; } const std::string& legacy_config() const { return legacy_config_; } void set_legacy_config(const std::string& value) { legacy_config_ = value; _has_field_.set(1000); } bool has_for_testing() const { return _has_field_[1001]; } const TestConfig& for_testing() const { return *for_testing_; } TestConfig* mutable_for_testing() { _has_field_.set(1001); return for_testing_.get(); } private: std::string name_{}; uint32_t target_buffer_{}; uint32_t trace_duration_ms_{}; uint32_t stop_timeout_ms_{}; bool enable_extra_guardrails_{}; DataSourceConfig_SessionInitiator session_initiator_{}; uint64_t tracing_session_id_{}; std::string ftrace_config_; // [lazy=true] std::string inode_file_config_; // [lazy=true] std::string process_stats_config_; // [lazy=true] std::string sys_stats_config_; // [lazy=true] std::string heapprofd_config_; // [lazy=true] std::string java_hprof_config_; // [lazy=true] std::string android_power_config_; // [lazy=true] std::string android_log_config_; // [lazy=true] std::string gpu_counter_config_; // [lazy=true] std::string packages_list_config_; // [lazy=true] std::string perf_event_config_; // [lazy=true] std::string vulkan_memory_config_; // [lazy=true] std::string track_event_config_; // [lazy=true] std::string android_polled_state_config_; // [lazy=true] ::protozero::CopyablePtr chrome_config_; ::protozero::CopyablePtr interceptor_config_; std::string legacy_config_{}; ::protozero::CopyablePtr for_testing_; // Allows to preserve unknown protobuf fields for compatibility // with future versions of .proto files. std::string unknown_fields_; std::bitset<1002> _has_field_{}; }; } // namespace perfetto } // namespace protos } // namespace gen #endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_DATA_SOURCE_CONFIG_PROTO_CPP_H_ /* * Copyright (C) 2017 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_CONFIG_H_ #define INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_CONFIG_H_ // Creates the aliases in the ::perfetto namespace, doing things like: // using ::perfetto::Foo = ::perfetto::protos::gen::Foo. // See comments in forward_decls.h for the historical reasons of this // indirection layer. // gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h" // gen_amalgamated expanded: #include "protos/perfetto/config/data_source_config.gen.h" #endif // INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_CONFIG_H_ // gen_amalgamated begin header: include/perfetto/tracing/core/data_source_descriptor.h // gen_amalgamated begin header: gen/protos/perfetto/common/data_source_descriptor.gen.h // DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin #ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_DATA_SOURCE_DESCRIPTOR_PROTO_CPP_H_ #define PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_DATA_SOURCE_DESCRIPTOR_PROTO_CPP_H_ #include #include #include #include #include // gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h" // gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h" // gen_amalgamated expanded: #include "perfetto/base/export.h" namespace perfetto { namespace protos { namespace gen { class DataSourceDescriptor; } // namespace perfetto } // namespace protos } // namespace gen namespace protozero { class Message; } // namespace protozero namespace perfetto { namespace protos { namespace gen { class PERFETTO_EXPORT DataSourceDescriptor : public ::protozero::CppMessageObj { public: enum FieldNumbers { kNameFieldNumber = 1, kWillNotifyOnStopFieldNumber = 2, kWillNotifyOnStartFieldNumber = 3, kHandlesIncrementalStateClearFieldNumber = 4, kGpuCounterDescriptorFieldNumber = 5, kTrackEventDescriptorFieldNumber = 6, }; DataSourceDescriptor(); ~DataSourceDescriptor() override; DataSourceDescriptor(DataSourceDescriptor&&) noexcept; DataSourceDescriptor& operator=(DataSourceDescriptor&&); DataSourceDescriptor(const DataSourceDescriptor&); DataSourceDescriptor& operator=(const DataSourceDescriptor&); bool operator==(const DataSourceDescriptor&) const; bool operator!=(const DataSourceDescriptor& other) const { return !(*this == other); } bool ParseFromArray(const void*, size_t) override; std::string SerializeAsString() const override; std::vector SerializeAsArray() const override; void Serialize(::protozero::Message*) const; bool has_name() const { return _has_field_[1]; } const std::string& name() const { return name_; } void set_name(const std::string& value) { name_ = value; _has_field_.set(1); } bool has_will_notify_on_stop() const { return _has_field_[2]; } bool will_notify_on_stop() const { return will_notify_on_stop_; } void set_will_notify_on_stop(bool value) { will_notify_on_stop_ = value; _has_field_.set(2); } bool has_will_notify_on_start() const { return _has_field_[3]; } bool will_notify_on_start() const { return will_notify_on_start_; } void set_will_notify_on_start(bool value) { will_notify_on_start_ = value; _has_field_.set(3); } bool has_handles_incremental_state_clear() const { return _has_field_[4]; } bool handles_incremental_state_clear() const { return handles_incremental_state_clear_; } void set_handles_incremental_state_clear(bool value) { handles_incremental_state_clear_ = value; _has_field_.set(4); } const std::string& gpu_counter_descriptor_raw() const { return gpu_counter_descriptor_; } void set_gpu_counter_descriptor_raw(const std::string& raw) { gpu_counter_descriptor_ = raw; _has_field_.set(5); } const std::string& track_event_descriptor_raw() const { return track_event_descriptor_; } void set_track_event_descriptor_raw(const std::string& raw) { track_event_descriptor_ = raw; _has_field_.set(6); } private: std::string name_{}; bool will_notify_on_stop_{}; bool will_notify_on_start_{}; bool handles_incremental_state_clear_{}; std::string gpu_counter_descriptor_; // [lazy=true] std::string track_event_descriptor_; // [lazy=true] // Allows to preserve unknown protobuf fields for compatibility // with future versions of .proto files. std::string unknown_fields_; std::bitset<7> _has_field_{}; }; } // namespace perfetto } // namespace protos } // namespace gen #endif // PERFETTO_PROTOS_PROTOS_PERFETTO_COMMON_DATA_SOURCE_DESCRIPTOR_PROTO_CPP_H_ /* * Copyright (C) 2017 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_DESCRIPTOR_H_ #define INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_DESCRIPTOR_H_ // Creates the aliases in the ::perfetto namespace, doing things like: // using ::perfetto::Foo = ::perfetto::protos::gen::Foo. // See comments in forward_decls.h for the historical reasons of this // indirection layer. // gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h" // gen_amalgamated expanded: #include "protos/perfetto/common/data_source_descriptor.gen.h" #endif // INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_DESCRIPTOR_H_ // gen_amalgamated begin header: include/perfetto/tracing/core/trace_config.h // gen_amalgamated begin header: gen/protos/perfetto/config/trace_config.gen.h // DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin #ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_TRACE_CONFIG_PROTO_CPP_H_ #define PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_TRACE_CONFIG_PROTO_CPP_H_ #include #include #include #include #include // gen_amalgamated expanded: #include "perfetto/protozero/cpp_message_obj.h" // gen_amalgamated expanded: #include "perfetto/protozero/copyable_ptr.h" // gen_amalgamated expanded: #include "perfetto/base/export.h" namespace perfetto { namespace protos { namespace gen { class TraceConfig; class TraceConfig_TraceFilter; class TraceConfig_IncidentReportConfig; class TraceConfig_IncrementalStateConfig; class TraceConfig_TriggerConfig; class TraceConfig_TriggerConfig_Trigger; class TraceConfig_GuardrailOverrides; class TraceConfig_StatsdMetadata; class TraceConfig_ProducerConfig; class TraceConfig_BuiltinDataSource; class TraceConfig_DataSource; class DataSourceConfig; class TestConfig; class TestConfig_DummyFields; class InterceptorConfig; class ChromeConfig; class TraceConfig_BufferConfig; enum TraceConfig_LockdownModeOperation : int; enum TraceConfig_CompressionType : int; enum TraceConfig_StatsdLogging : int; enum TraceConfig_TriggerConfig_TriggerMode : int; enum BuiltinClock : int; enum DataSourceConfig_SessionInitiator : int; enum ChromeConfig_ClientPriority : int; enum TraceConfig_BufferConfig_FillPolicy : int; } // namespace perfetto } // namespace protos } // namespace gen namespace protozero { class Message; } // namespace protozero namespace perfetto { namespace protos { namespace gen { enum TraceConfig_LockdownModeOperation : int { TraceConfig_LockdownModeOperation_LOCKDOWN_UNCHANGED = 0, TraceConfig_LockdownModeOperation_LOCKDOWN_CLEAR = 1, TraceConfig_LockdownModeOperation_LOCKDOWN_SET = 2, }; enum TraceConfig_CompressionType : int { TraceConfig_CompressionType_COMPRESSION_TYPE_UNSPECIFIED = 0, TraceConfig_CompressionType_COMPRESSION_TYPE_DEFLATE = 1, }; enum TraceConfig_StatsdLogging : int { TraceConfig_StatsdLogging_STATSD_LOGGING_UNSPECIFIED = 0, TraceConfig_StatsdLogging_STATSD_LOGGING_ENABLED = 1, TraceConfig_StatsdLogging_STATSD_LOGGING_DISABLED = 2, }; enum TraceConfig_TriggerConfig_TriggerMode : int { TraceConfig_TriggerConfig_TriggerMode_UNSPECIFIED = 0, TraceConfig_TriggerConfig_TriggerMode_START_TRACING = 1, TraceConfig_TriggerConfig_TriggerMode_STOP_TRACING = 2, }; enum TraceConfig_BufferConfig_FillPolicy : int { TraceConfig_BufferConfig_FillPolicy_UNSPECIFIED = 0, TraceConfig_BufferConfig_FillPolicy_RING_BUFFER = 1, TraceConfig_BufferConfig_FillPolicy_DISCARD = 2, }; class PERFETTO_EXPORT TraceConfig : public ::protozero::CppMessageObj { public: using BufferConfig = TraceConfig_BufferConfig; using DataSource = TraceConfig_DataSource; using BuiltinDataSource = TraceConfig_BuiltinDataSource; using ProducerConfig = TraceConfig_ProducerConfig; using StatsdMetadata = TraceConfig_StatsdMetadata; using GuardrailOverrides = TraceConfig_GuardrailOverrides; using TriggerConfig = TraceConfig_TriggerConfig; using IncrementalStateConfig = TraceConfig_IncrementalStateConfig; using IncidentReportConfig = TraceConfig_IncidentReportConfig; using TraceFilter = TraceConfig_TraceFilter; using LockdownModeOperation = TraceConfig_LockdownModeOperation; static constexpr auto LOCKDOWN_UNCHANGED = TraceConfig_LockdownModeOperation_LOCKDOWN_UNCHANGED; static constexpr auto LOCKDOWN_CLEAR = TraceConfig_LockdownModeOperation_LOCKDOWN_CLEAR; static constexpr auto LOCKDOWN_SET = TraceConfig_LockdownModeOperation_LOCKDOWN_SET; static constexpr auto LockdownModeOperation_MIN = TraceConfig_LockdownModeOperation_LOCKDOWN_UNCHANGED; static constexpr auto LockdownModeOperation_MAX = TraceConfig_LockdownModeOperation_LOCKDOWN_SET; using CompressionType = TraceConfig_CompressionType; static constexpr auto COMPRESSION_TYPE_UNSPECIFIED = TraceConfig_CompressionType_COMPRESSION_TYPE_UNSPECIFIED; static constexpr auto COMPRESSION_TYPE_DEFLATE = TraceConfig_CompressionType_COMPRESSION_TYPE_DEFLATE; static constexpr auto CompressionType_MIN = TraceConfig_CompressionType_COMPRESSION_TYPE_UNSPECIFIED; static constexpr auto CompressionType_MAX = TraceConfig_CompressionType_COMPRESSION_TYPE_DEFLATE; using StatsdLogging = TraceConfig_StatsdLogging; static constexpr auto STATSD_LOGGING_UNSPECIFIED = TraceConfig_StatsdLogging_STATSD_LOGGING_UNSPECIFIED; static constexpr auto STATSD_LOGGING_ENABLED = TraceConfig_StatsdLogging_STATSD_LOGGING_ENABLED; static constexpr auto STATSD_LOGGING_DISABLED = TraceConfig_StatsdLogging_STATSD_LOGGING_DISABLED; static constexpr auto StatsdLogging_MIN = TraceConfig_StatsdLogging_STATSD_LOGGING_UNSPECIFIED; static constexpr auto StatsdLogging_MAX = TraceConfig_StatsdLogging_STATSD_LOGGING_DISABLED; enum FieldNumbers { kBuffersFieldNumber = 1, kDataSourcesFieldNumber = 2, kBuiltinDataSourcesFieldNumber = 20, kDurationMsFieldNumber = 3, kEnableExtraGuardrailsFieldNumber = 4, kLockdownModeFieldNumber = 5, kProducersFieldNumber = 6, kStatsdMetadataFieldNumber = 7, kWriteIntoFileFieldNumber = 8, kOutputPathFieldNumber = 29, kFileWritePeriodMsFieldNumber = 9, kMaxFileSizeBytesFieldNumber = 10, kGuardrailOverridesFieldNumber = 11, kDeferredStartFieldNumber = 12, kFlushPeriodMsFieldNumber = 13, kFlushTimeoutMsFieldNumber = 14, kDataSourceStopTimeoutMsFieldNumber = 23, kNotifyTraceurFieldNumber = 16, kBugreportScoreFieldNumber = 30, kTriggerConfigFieldNumber = 17, kActivateTriggersFieldNumber = 18, kIncrementalStateConfigFieldNumber = 21, kAllowUserBuildTracingFieldNumber = 19, kUniqueSessionNameFieldNumber = 22, kCompressionTypeFieldNumber = 24, kIncidentReportConfigFieldNumber = 25, kStatsdLoggingFieldNumber = 31, kTraceUuidMsbFieldNumber = 27, kTraceUuidLsbFieldNumber = 28, kTraceFilterFieldNumber = 32, }; TraceConfig(); ~TraceConfig() override; TraceConfig(TraceConfig&&) noexcept; TraceConfig& operator=(TraceConfig&&); TraceConfig(const TraceConfig&); TraceConfig& operator=(const TraceConfig&); bool operator==(const TraceConfig&) const; bool operator!=(const TraceConfig& other) const { return !(*this == other); } bool ParseFromArray(const void*, size_t) override; std::string SerializeAsString() const override; std::vector SerializeAsArray() const override; void Serialize(::protozero::Message*) const; const std::vector& buffers() const { return buffers_; } std::vector* mutable_buffers() { return &buffers_; } int buffers_size() const; void clear_buffers(); TraceConfig_BufferConfig* add_buffers(); const std::vector& data_sources() const { return data_sources_; } std::vector* mutable_data_sources() { return &data_sources_; } int data_sources_size() const; void clear_data_sources(); TraceConfig_DataSource* add_data_sources(); bool has_builtin_data_sources() const { return _has_field_[20]; } const TraceConfig_BuiltinDataSource& builtin_data_sources() const { return *builtin_data_sources_; } TraceConfig_BuiltinDataSource* mutable_builtin_data_sources() { _has_field_.set(20); return builtin_data_sources_.get(); } bool has_duration_ms() const { return _has_field_[3]; } uint32_t duration_ms() const { return duration_ms_; } void set_duration_ms(uint32_t value) { duration_ms_ = value; _has_field_.set(3); } bool has_enable_extra_guardrails() const { return _has_field_[4]; } bool enable_extra_guardrails() const { return enable_extra_guardrails_; } void set_enable_extra_guardrails(bool value) { enable_extra_guardrails_ = value; _has_field_.set(4); } bool has_lockdown_mode() const { return _has_field_[5]; } TraceConfig_LockdownModeOperation lockdown_mode() const { return lockdown_mode_; } void set_lockdown_mode(TraceConfig_LockdownModeOperation value) { lockdown_mode_ = value; _has_field_.set(5); } const std::vector& producers() const { return producers_; } std::vector* mutable_producers() { return &producers_; } int producers_size() const; void clear_producers(); TraceConfig_ProducerConfig* add_producers(); bool has_statsd_metadata() const { return _has_field_[7]; } const TraceConfig_StatsdMetadata& statsd_metadata() const { return *statsd_metadata_; } TraceConfig_StatsdMetadata* mutable_statsd_metadata() { _has_field_.set(7); return statsd_metadata_.get(); } bool has_write_into_file() const { return _has_field_[8]; } bool write_into_file() const { return write_into_file_; } void set_write_into_file(bool value) { write_into_file_ = value; _has_field_.set(8); } bool has_output_path() const { return _has_field_[29]; } const std::string& output_path() const { return output_path_; } void set_output_path(const std::string& value) { output_path_ = value; _has_field_.set(29); } bool has_file_write_period_ms() const { return _has_field_[9]; } uint32_t file_write_period_ms() const { return file_write_period_ms_; } void set_file_write_period_ms(uint32_t value) { file_write_period_ms_ = value; _has_field_.set(9); } bool has_max_file_size_bytes() const { return _has_field_[10]; } uint64_t max_file_size_bytes() const { return max_file_size_bytes_; } void set_max_file_size_bytes(uint64_t value) { max_file_size_bytes_ = value; _has_field_.set(10); } bool has_guardrail_overrides() const { return _has_field_[11]; } const TraceConfig_GuardrailOverrides& guardrail_overrides() const { return *guardrail_overrides_; } TraceConfig_GuardrailOverrides* mutable_guardrail_overrides() { _has_field_.set(11); return guardrail_overrides_.get(); } bool has_deferred_start() const { return _has_field_[12]; } bool deferred_start() const { return deferred_start_; } void set_deferred_start(bool value) { deferred_start_ = value; _has_field_.set(12); } bool has_flush_period_ms() const { return _has_field_[13]; } uint32_t flush_period_ms() const { return flush_period_ms_; } void set_flush_period_ms(uint32_t value) { flush_period_ms_ = value; _has_field_.set(13); } bool has_flush_timeout_ms() const { return _has_field_[14]; } uint32_t flush_timeout_ms() const { return flush_timeout_ms_; } void set_flush_timeout_ms(uint32_t value) { flush_timeout_ms_ = value; _has_field_.set(14); } bool has_data_source_stop_timeout_ms() const { return _has_field_[23]; } uint32_t data_source_stop_timeout_ms() const { return data_source_stop_timeout_ms_; } void set_data_source_stop_timeout_ms(uint32_t value) { data_source_stop_timeout_ms_ = value; _has_field_.set(23); } bool has_notify_traceur() const { return _has_field_[16]; } bool notify_traceur() const { return notify_traceur_; } void set_notify_traceur(bool value) { notify_traceur_ = value; _has_field_.set(16); } bool has_bugreport_score() const { return _has_field_[30]; } int32_t bugreport_score() const { return bugreport_score_; } void set_bugreport_score(int32_t value) { bugreport_score_ = value; _has_field_.set(30); } bool has_trigger_config() const { return _has_field_[17]; } const TraceConfig_TriggerConfig& trigger_config() const { return *trigger_config_; } TraceConfig_TriggerConfig* mutable_trigger_config() { _has_field_.set(17); return trigger_config_.get(); } const std::vector& activate_triggers() const { return activate_triggers_; } std::vector* mutable_activate_triggers() { return &activate_triggers_; } int activate_triggers_size() const { return static_cast(activate_triggers_.size()); } void clear_activate_triggers() { activate_triggers_.clear(); } void add_activate_triggers(std::string value) { activate_triggers_.emplace_back(value); } std::string* add_activate_triggers() { activate_triggers_.emplace_back(); return &activate_triggers_.back(); } bool has_incremental_state_config() const { return _has_field_[21]; } const TraceConfig_IncrementalStateConfig& incremental_state_config() const { return *incremental_state_config_; } TraceConfig_IncrementalStateConfig* mutable_incremental_state_config() { _has_field_.set(21); return incremental_state_config_.get(); } bool has_allow_user_build_tracing() const { return _has_field_[19]; } bool allow_user_build_tracing() const { return allow_user_build_tracing_; } void set_allow_user_build_tracing(bool value) { allow_user_build_tracing_ = value; _has_field_.set(19); } bool has_unique_session_name() const { return _has_field_[22]; } const std::string& unique_session_name() const { return unique_session_name_; } void set_unique_session_name(const std::string& value) { unique_session_name_ = value; _has_field_.set(22); } bool has_compression_type() const { return _has_field_[24]; } TraceConfig_CompressionType compression_type() const { return compression_type_; } void set_compression_type(TraceConfig_CompressionType value) { compression_type_ = value; _has_field_.set(24); } bool has_incident_report_config() const { return _has_field_[25]; } const TraceConfig_IncidentReportConfig& incident_report_config() const { return *incident_report_config_; } TraceConfig_IncidentReportConfig* mutable_incident_report_config() { _has_field_.set(25); return incident_report_config_.get(); } bool has_statsd_logging() const { return _has_field_[31]; } TraceConfig_StatsdLogging statsd_logging() const { return statsd_logging_; } void set_statsd_logging(TraceConfig_StatsdLogging value) { statsd_logging_ = value; _has_field_.set(31); } bool has_trace_uuid_msb() const { return _has_field_[27]; } int64_t trace_uuid_msb() const { return trace_uuid_msb_; } void set_trace_uuid_msb(int64_t value) { trace_uuid_msb_ = value; _has_field_.set(27); } bool has_trace_uuid_lsb() const { return _has_field_[28]; } int64_t trace_uuid_lsb() const { return trace_uuid_lsb_; } void set_trace_uuid_lsb(int64_t value) { trace_uuid_lsb_ = value; _has_field_.set(28); } bool has_trace_filter() const { return _has_field_[32]; } const TraceConfig_TraceFilter& trace_filter() const { return *trace_filter_; } TraceConfig_TraceFilter* mutable_trace_filter() { _has_field_.set(32); return trace_filter_.get(); } private: std::vector buffers_; std::vector data_sources_; ::protozero::CopyablePtr builtin_data_sources_; uint32_t duration_ms_{}; bool enable_extra_guardrails_{}; TraceConfig_LockdownModeOperation lockdown_mode_{}; std::vector producers_; ::protozero::CopyablePtr statsd_metadata_; bool write_into_file_{}; std::string output_path_{}; uint32_t file_write_period_ms_{}; uint64_t max_file_size_bytes_{}; ::protozero::CopyablePtr guardrail_overrides_; bool deferred_start_{}; uint32_t flush_period_ms_{}; uint32_t flush_timeout_ms_{}; uint32_t data_source_stop_timeout_ms_{}; bool notify_traceur_{}; int32_t bugreport_score_{}; ::protozero::CopyablePtr trigger_config_; std::vector activate_triggers_; ::protozero::CopyablePtr incremental_state_config_; bool allow_user_build_tracing_{}; std::string unique_session_name_{}; TraceConfig_CompressionType compression_type_{}; ::protozero::CopyablePtr incident_report_config_; TraceConfig_StatsdLogging statsd_logging_{}; int64_t trace_uuid_msb_{}; int64_t trace_uuid_lsb_{}; ::protozero::CopyablePtr trace_filter_; // Allows to preserve unknown protobuf fields for compatibility // with future versions of .proto files. std::string unknown_fields_; std::bitset<33> _has_field_{}; }; class PERFETTO_EXPORT TraceConfig_TraceFilter : public ::protozero::CppMessageObj { public: enum FieldNumbers { kBytecodeFieldNumber = 1, }; TraceConfig_TraceFilter(); ~TraceConfig_TraceFilter() override; TraceConfig_TraceFilter(TraceConfig_TraceFilter&&) noexcept; TraceConfig_TraceFilter& operator=(TraceConfig_TraceFilter&&); TraceConfig_TraceFilter(const TraceConfig_TraceFilter&); TraceConfig_TraceFilter& operator=(const TraceConfig_TraceFilter&); bool operator==(const TraceConfig_TraceFilter&) const; bool operator!=(const TraceConfig_TraceFilter& other) const { return !(*this == other); } bool ParseFromArray(const void*, size_t) override; std::string SerializeAsString() const override; std::vector SerializeAsArray() const override; void Serialize(::protozero::Message*) const; bool has_bytecode() const { return _has_field_[1]; } const std::string& bytecode() const { return bytecode_; } void set_bytecode(const std::string& value) { bytecode_ = value; _has_field_.set(1); } void set_bytecode(const void* p, size_t s) { bytecode_.assign(reinterpret_cast(p), s); _has_field_.set(1); } private: std::string bytecode_{}; // Allows to preserve unknown protobuf fields for compatibility // with future versions of .proto files. std::string unknown_fields_; std::bitset<2> _has_field_{}; }; class PERFETTO_EXPORT TraceConfig_IncidentReportConfig : public ::protozero::CppMessageObj { public: enum FieldNumbers { kDestinationPackageFieldNumber = 1, kDestinationClassFieldNumber = 2, kPrivacyLevelFieldNumber = 3, kSkipIncidentdFieldNumber = 5, kSkipDropboxFieldNumber = 4, }; TraceConfig_IncidentReportConfig(); ~TraceConfig_IncidentReportConfig() override; TraceConfig_IncidentReportConfig(TraceConfig_IncidentReportConfig&&) noexcept; TraceConfig_IncidentReportConfig& operator=(TraceConfig_IncidentReportConfig&&); TraceConfig_IncidentReportConfig(const TraceConfig_IncidentReportConfig&); TraceConfig_IncidentReportConfig& operator=(const TraceConfig_IncidentReportConfig&); bool operator==(const TraceConfig_IncidentReportConfig&) const; bool operator!=(const TraceConfig_IncidentReportConfig& other) const { return !(*this == other); } bool ParseFromArray(const void*, size_t) override; std::string SerializeAsString() const override; std::vector SerializeAsArray() const override; void Serialize(::protozero::Message*) const; bool has_destination_package() const { return _has_field_[1]; } const std::string& destination_package() const { return destination_package_; } void set_destination_package(const std::string& value) { destination_package_ = value; _has_field_.set(1); } bool has_destination_class() const { return _has_field_[2]; } const std::string& destination_class() const { return destination_class_; } void set_destination_class(const std::string& value) { destination_class_ = value; _has_field_.set(2); } bool has_privacy_level() const { return _has_field_[3]; } int32_t privacy_level() const { return privacy_level_; } void set_privacy_level(int32_t value) { privacy_level_ = value; _has_field_.set(3); } bool has_skip_incidentd() const { return _has_field_[5]; } bool skip_incidentd() const { return skip_incidentd_; } void set_skip_incidentd(bool value) { skip_incidentd_ = value; _has_field_.set(5); } bool has_skip_dropbox() const { return _has_field_[4]; } bool skip_dropbox() const { return skip_dropbox_; } void set_skip_dropbox(bool value) { skip_dropbox_ = value; _has_field_.set(4); } private: std::string destination_package_{}; std::string destination_class_{}; int32_t privacy_level_{}; bool skip_incidentd_{}; bool skip_dropbox_{}; // Allows to preserve unknown protobuf fields for compatibility // with future versions of .proto files. std::string unknown_fields_; std::bitset<6> _has_field_{}; }; class PERFETTO_EXPORT TraceConfig_IncrementalStateConfig : public ::protozero::CppMessageObj { public: enum FieldNumbers { kClearPeriodMsFieldNumber = 1, }; TraceConfig_IncrementalStateConfig(); ~TraceConfig_IncrementalStateConfig() override; TraceConfig_IncrementalStateConfig(TraceConfig_IncrementalStateConfig&&) noexcept; TraceConfig_IncrementalStateConfig& operator=(TraceConfig_IncrementalStateConfig&&); TraceConfig_IncrementalStateConfig(const TraceConfig_IncrementalStateConfig&); TraceConfig_IncrementalStateConfig& operator=(const TraceConfig_IncrementalStateConfig&); bool operator==(const TraceConfig_IncrementalStateConfig&) const; bool operator!=(const TraceConfig_IncrementalStateConfig& other) const { return !(*this == other); } bool ParseFromArray(const void*, size_t) override; std::string SerializeAsString() const override; std::vector SerializeAsArray() const override; void Serialize(::protozero::Message*) const; bool has_clear_period_ms() const { return _has_field_[1]; } uint32_t clear_period_ms() const { return clear_period_ms_; } void set_clear_period_ms(uint32_t value) { clear_period_ms_ = value; _has_field_.set(1); } private: uint32_t clear_period_ms_{}; // Allows to preserve unknown protobuf fields for compatibility // with future versions of .proto files. std::string unknown_fields_; std::bitset<2> _has_field_{}; }; class PERFETTO_EXPORT TraceConfig_TriggerConfig : public ::protozero::CppMessageObj { public: using Trigger = TraceConfig_TriggerConfig_Trigger; using TriggerMode = TraceConfig_TriggerConfig_TriggerMode; static constexpr auto UNSPECIFIED = TraceConfig_TriggerConfig_TriggerMode_UNSPECIFIED; static constexpr auto START_TRACING = TraceConfig_TriggerConfig_TriggerMode_START_TRACING; static constexpr auto STOP_TRACING = TraceConfig_TriggerConfig_TriggerMode_STOP_TRACING; static constexpr auto TriggerMode_MIN = TraceConfig_TriggerConfig_TriggerMode_UNSPECIFIED; static constexpr auto TriggerMode_MAX = TraceConfig_TriggerConfig_TriggerMode_STOP_TRACING; enum FieldNumbers { kTriggerModeFieldNumber = 1, kTriggersFieldNumber = 2, kTriggerTimeoutMsFieldNumber = 3, }; TraceConfig_TriggerConfig(); ~TraceConfig_TriggerConfig() override; TraceConfig_TriggerConfig(TraceConfig_TriggerConfig&&) noexcept; TraceConfig_TriggerConfig& operator=(TraceConfig_TriggerConfig&&); TraceConfig_TriggerConfig(const TraceConfig_TriggerConfig&); TraceConfig_TriggerConfig& operator=(const TraceConfig_TriggerConfig&); bool operator==(const TraceConfig_TriggerConfig&) const; bool operator!=(const TraceConfig_TriggerConfig& other) const { return !(*this == other); } bool ParseFromArray(const void*, size_t) override; std::string SerializeAsString() const override; std::vector SerializeAsArray() const override; void Serialize(::protozero::Message*) const; bool has_trigger_mode() const { return _has_field_[1]; } TraceConfig_TriggerConfig_TriggerMode trigger_mode() const { return trigger_mode_; } void set_trigger_mode(TraceConfig_TriggerConfig_TriggerMode value) { trigger_mode_ = value; _has_field_.set(1); } const std::vector& triggers() const { return triggers_; } std::vector* mutable_triggers() { return &triggers_; } int triggers_size() const; void clear_triggers(); TraceConfig_TriggerConfig_Trigger* add_triggers(); bool has_trigger_timeout_ms() const { return _has_field_[3]; } uint32_t trigger_timeout_ms() const { return trigger_timeout_ms_; } void set_trigger_timeout_ms(uint32_t value) { trigger_timeout_ms_ = value; _has_field_.set(3); } private: TraceConfig_TriggerConfig_TriggerMode trigger_mode_{}; std::vector triggers_; uint32_t trigger_timeout_ms_{}; // Allows to preserve unknown protobuf fields for compatibility // with future versions of .proto files. std::string unknown_fields_; std::bitset<4> _has_field_{}; }; class PERFETTO_EXPORT TraceConfig_TriggerConfig_Trigger : public ::protozero::CppMessageObj { public: enum FieldNumbers { kNameFieldNumber = 1, kProducerNameRegexFieldNumber = 2, kStopDelayMsFieldNumber = 3, kMaxPer24HFieldNumber = 4, kSkipProbabilityFieldNumber = 5, }; TraceConfig_TriggerConfig_Trigger(); ~TraceConfig_TriggerConfig_Trigger() override; TraceConfig_TriggerConfig_Trigger(TraceConfig_TriggerConfig_Trigger&&) noexcept; TraceConfig_TriggerConfig_Trigger& operator=(TraceConfig_TriggerConfig_Trigger&&); TraceConfig_TriggerConfig_Trigger(const TraceConfig_TriggerConfig_Trigger&); TraceConfig_TriggerConfig_Trigger& operator=(const TraceConfig_TriggerConfig_Trigger&); bool operator==(const TraceConfig_TriggerConfig_Trigger&) const; bool operator!=(const TraceConfig_TriggerConfig_Trigger& other) const { return !(*this == other); } bool ParseFromArray(const void*, size_t) override; std::string SerializeAsString() const override; std::vector SerializeAsArray() const override; void Serialize(::protozero::Message*) const; bool has_name() const { return _has_field_[1]; } const std::string& name() const { return name_; } void set_name(const std::string& value) { name_ = value; _has_field_.set(1); } bool has_producer_name_regex() const { return _has_field_[2]; } const std::string& producer_name_regex() const { return producer_name_regex_; } void set_producer_name_regex(const std::string& value) { producer_name_regex_ = value; _has_field_.set(2); } bool has_stop_delay_ms() const { return _has_field_[3]; } uint32_t stop_delay_ms() const { return stop_delay_ms_; } void set_stop_delay_ms(uint32_t value) { stop_delay_ms_ = value; _has_field_.set(3); } bool has_max_per_24_h() const { return _has_field_[4]; } uint32_t max_per_24_h() const { return max_per_24_h_; } void set_max_per_24_h(uint32_t value) { max_per_24_h_ = value; _has_field_.set(4); } bool has_skip_probability() const { return _has_field_[5]; } double skip_probability() const { return skip_probability_; } void set_skip_probability(double value) { skip_probability_ = value; _has_field_.set(5); } private: std::string name_{}; std::string producer_name_regex_{}; uint32_t stop_delay_ms_{}; uint32_t max_per_24_h_{}; double skip_probability_{}; // Allows to preserve unknown protobuf fields for compatibility // with future versions of .proto files. std::string unknown_fields_; std::bitset<6> _has_field_{}; }; class PERFETTO_EXPORT TraceConfig_GuardrailOverrides : public ::protozero::CppMessageObj { public: enum FieldNumbers { kMaxUploadPerDayBytesFieldNumber = 1, }; TraceConfig_GuardrailOverrides(); ~TraceConfig_GuardrailOverrides() override; TraceConfig_GuardrailOverrides(TraceConfig_GuardrailOverrides&&) noexcept; TraceConfig_GuardrailOverrides& operator=(TraceConfig_GuardrailOverrides&&); TraceConfig_GuardrailOverrides(const TraceConfig_GuardrailOverrides&); TraceConfig_GuardrailOverrides& operator=(const TraceConfig_GuardrailOverrides&); bool operator==(const TraceConfig_GuardrailOverrides&) const; bool operator!=(const TraceConfig_GuardrailOverrides& other) const { return !(*this == other); } bool ParseFromArray(const void*, size_t) override; std::string SerializeAsString() const override; std::vector SerializeAsArray() const override; void Serialize(::protozero::Message*) const; bool has_max_upload_per_day_bytes() const { return _has_field_[1]; } uint64_t max_upload_per_day_bytes() const { return max_upload_per_day_bytes_; } void set_max_upload_per_day_bytes(uint64_t value) { max_upload_per_day_bytes_ = value; _has_field_.set(1); } private: uint64_t max_upload_per_day_bytes_{}; // Allows to preserve unknown protobuf fields for compatibility // with future versions of .proto files. std::string unknown_fields_; std::bitset<2> _has_field_{}; }; class PERFETTO_EXPORT TraceConfig_StatsdMetadata : public ::protozero::CppMessageObj { public: enum FieldNumbers { kTriggeringAlertIdFieldNumber = 1, kTriggeringConfigUidFieldNumber = 2, kTriggeringConfigIdFieldNumber = 3, kTriggeringSubscriptionIdFieldNumber = 4, }; TraceConfig_StatsdMetadata(); ~TraceConfig_StatsdMetadata() override; TraceConfig_StatsdMetadata(TraceConfig_StatsdMetadata&&) noexcept; TraceConfig_StatsdMetadata& operator=(TraceConfig_StatsdMetadata&&); TraceConfig_StatsdMetadata(const TraceConfig_StatsdMetadata&); TraceConfig_StatsdMetadata& operator=(const TraceConfig_StatsdMetadata&); bool operator==(const TraceConfig_StatsdMetadata&) const; bool operator!=(const TraceConfig_StatsdMetadata& other) const { return !(*this == other); } bool ParseFromArray(const void*, size_t) override; std::string SerializeAsString() const override; std::vector SerializeAsArray() const override; void Serialize(::protozero::Message*) const; bool has_triggering_alert_id() const { return _has_field_[1]; } int64_t triggering_alert_id() const { return triggering_alert_id_; } void set_triggering_alert_id(int64_t value) { triggering_alert_id_ = value; _has_field_.set(1); } bool has_triggering_config_uid() const { return _has_field_[2]; } int32_t triggering_config_uid() const { return triggering_config_uid_; } void set_triggering_config_uid(int32_t value) { triggering_config_uid_ = value; _has_field_.set(2); } bool has_triggering_config_id() const { return _has_field_[3]; } int64_t triggering_config_id() const { return triggering_config_id_; } void set_triggering_config_id(int64_t value) { triggering_config_id_ = value; _has_field_.set(3); } bool has_triggering_subscription_id() const { return _has_field_[4]; } int64_t triggering_subscription_id() const { return triggering_subscription_id_; } void set_triggering_subscription_id(int64_t value) { triggering_subscription_id_ = value; _has_field_.set(4); } private: int64_t triggering_alert_id_{}; int32_t triggering_config_uid_{}; int64_t triggering_config_id_{}; int64_t triggering_subscription_id_{}; // Allows to preserve unknown protobuf fields for compatibility // with future versions of .proto files. std::string unknown_fields_; std::bitset<5> _has_field_{}; }; class PERFETTO_EXPORT TraceConfig_ProducerConfig : public ::protozero::CppMessageObj { public: enum FieldNumbers { kProducerNameFieldNumber = 1, kShmSizeKbFieldNumber = 2, kPageSizeKbFieldNumber = 3, }; TraceConfig_ProducerConfig(); ~TraceConfig_ProducerConfig() override; TraceConfig_ProducerConfig(TraceConfig_ProducerConfig&&) noexcept; TraceConfig_ProducerConfig& operator=(TraceConfig_ProducerConfig&&); TraceConfig_ProducerConfig(const TraceConfig_ProducerConfig&); TraceConfig_ProducerConfig& operator=(const TraceConfig_ProducerConfig&); bool operator==(const TraceConfig_ProducerConfig&) const; bool operator!=(const TraceConfig_ProducerConfig& other) const { return !(*this == other); } bool ParseFromArray(const void*, size_t) override; std::string SerializeAsString() const override; std::vector SerializeAsArray() const override; void Serialize(::protozero::Message*) const; bool has_producer_name() const { return _has_field_[1]; } const std::string& producer_name() const { return producer_name_; } void set_producer_name(const std::string& value) { producer_name_ = value; _has_field_.set(1); } bool has_shm_size_kb() const { return _has_field_[2]; } uint32_t shm_size_kb() const { return shm_size_kb_; } void set_shm_size_kb(uint32_t value) { shm_size_kb_ = value; _has_field_.set(2); } bool has_page_size_kb() const { return _has_field_[3]; } uint32_t page_size_kb() const { return page_size_kb_; } void set_page_size_kb(uint32_t value) { page_size_kb_ = value; _has_field_.set(3); } private: std::string producer_name_{}; uint32_t shm_size_kb_{}; uint32_t page_size_kb_{}; // Allows to preserve unknown protobuf fields for compatibility // with future versions of .proto files. std::string unknown_fields_; std::bitset<4> _has_field_{}; }; class PERFETTO_EXPORT TraceConfig_BuiltinDataSource : public ::protozero::CppMessageObj { public: enum FieldNumbers { kDisableClockSnapshottingFieldNumber = 1, kDisableTraceConfigFieldNumber = 2, kDisableSystemInfoFieldNumber = 3, kDisableServiceEventsFieldNumber = 4, kPrimaryTraceClockFieldNumber = 5, kSnapshotIntervalMsFieldNumber = 6, kPreferSuspendClockForSnapshotFieldNumber = 7, }; TraceConfig_BuiltinDataSource(); ~TraceConfig_BuiltinDataSource() override; TraceConfig_BuiltinDataSource(TraceConfig_BuiltinDataSource&&) noexcept; TraceConfig_BuiltinDataSource& operator=(TraceConfig_BuiltinDataSource&&); TraceConfig_BuiltinDataSource(const TraceConfig_BuiltinDataSource&); TraceConfig_BuiltinDataSource& operator=(const TraceConfig_BuiltinDataSource&); bool operator==(const TraceConfig_BuiltinDataSource&) const; bool operator!=(const TraceConfig_BuiltinDataSource& other) const { return !(*this == other); } bool ParseFromArray(const void*, size_t) override; std::string SerializeAsString() const override; std::vector SerializeAsArray() const override; void Serialize(::protozero::Message*) const; bool has_disable_clock_snapshotting() const { return _has_field_[1]; } bool disable_clock_snapshotting() const { return disable_clock_snapshotting_; } void set_disable_clock_snapshotting(bool value) { disable_clock_snapshotting_ = value; _has_field_.set(1); } bool has_disable_trace_config() const { return _has_field_[2]; } bool disable_trace_config() const { return disable_trace_config_; } void set_disable_trace_config(bool value) { disable_trace_config_ = value; _has_field_.set(2); } bool has_disable_system_info() const { return _has_field_[3]; } bool disable_system_info() const { return disable_system_info_; } void set_disable_system_info(bool value) { disable_system_info_ = value; _has_field_.set(3); } bool has_disable_service_events() const { return _has_field_[4]; } bool disable_service_events() const { return disable_service_events_; } void set_disable_service_events(bool value) { disable_service_events_ = value; _has_field_.set(4); } bool has_primary_trace_clock() const { return _has_field_[5]; } BuiltinClock primary_trace_clock() const { return primary_trace_clock_; } void set_primary_trace_clock(BuiltinClock value) { primary_trace_clock_ = value; _has_field_.set(5); } bool has_snapshot_interval_ms() const { return _has_field_[6]; } uint32_t snapshot_interval_ms() const { return snapshot_interval_ms_; } void set_snapshot_interval_ms(uint32_t value) { snapshot_interval_ms_ = value; _has_field_.set(6); } bool has_prefer_suspend_clock_for_snapshot() const { return _has_field_[7]; } bool prefer_suspend_clock_for_snapshot() const { return prefer_suspend_clock_for_snapshot_; } void set_prefer_suspend_clock_for_snapshot(bool value) { prefer_suspend_clock_for_snapshot_ = value; _has_field_.set(7); } private: bool disable_clock_snapshotting_{}; bool disable_trace_config_{}; bool disable_system_info_{}; bool disable_service_events_{}; BuiltinClock primary_trace_clock_{}; uint32_t snapshot_interval_ms_{}; bool prefer_suspend_clock_for_snapshot_{}; // Allows to preserve unknown protobuf fields for compatibility // with future versions of .proto files. std::string unknown_fields_; std::bitset<8> _has_field_{}; }; class PERFETTO_EXPORT TraceConfig_DataSource : public ::protozero::CppMessageObj { public: enum FieldNumbers { kConfigFieldNumber = 1, kProducerNameFilterFieldNumber = 2, kProducerNameRegexFilterFieldNumber = 3, }; TraceConfig_DataSource(); ~TraceConfig_DataSource() override; TraceConfig_DataSource(TraceConfig_DataSource&&) noexcept; TraceConfig_DataSource& operator=(TraceConfig_DataSource&&); TraceConfig_DataSource(const TraceConfig_DataSource&); TraceConfig_DataSource& operator=(const TraceConfig_DataSource&); bool operator==(const TraceConfig_DataSource&) const; bool operator!=(const TraceConfig_DataSource& other) const { return !(*this == other); } bool ParseFromArray(const void*, size_t) override; std::string SerializeAsString() const override; std::vector SerializeAsArray() const override; void Serialize(::protozero::Message*) const; bool has_config() const { return _has_field_[1]; } const DataSourceConfig& config() const { return *config_; } DataSourceConfig* mutable_config() { _has_field_.set(1); return config_.get(); } const std::vector& producer_name_filter() const { return producer_name_filter_; } std::vector* mutable_producer_name_filter() { return &producer_name_filter_; } int producer_name_filter_size() const { return static_cast(producer_name_filter_.size()); } void clear_producer_name_filter() { producer_name_filter_.clear(); } void add_producer_name_filter(std::string value) { producer_name_filter_.emplace_back(value); } std::string* add_producer_name_filter() { producer_name_filter_.emplace_back(); return &producer_name_filter_.back(); } const std::vector& producer_name_regex_filter() const { return producer_name_regex_filter_; } std::vector* mutable_producer_name_regex_filter() { return &producer_name_regex_filter_; } int producer_name_regex_filter_size() const { return static_cast(producer_name_regex_filter_.size()); } void clear_producer_name_regex_filter() { producer_name_regex_filter_.clear(); } void add_producer_name_regex_filter(std::string value) { producer_name_regex_filter_.emplace_back(value); } std::string* add_producer_name_regex_filter() { producer_name_regex_filter_.emplace_back(); return &producer_name_regex_filter_.back(); } private: ::protozero::CopyablePtr config_; std::vector producer_name_filter_; std::vector producer_name_regex_filter_; // Allows to preserve unknown protobuf fields for compatibility // with future versions of .proto files. std::string unknown_fields_; std::bitset<4> _has_field_{}; }; class PERFETTO_EXPORT TraceConfig_BufferConfig : public ::protozero::CppMessageObj { public: using FillPolicy = TraceConfig_BufferConfig_FillPolicy; static constexpr auto UNSPECIFIED = TraceConfig_BufferConfig_FillPolicy_UNSPECIFIED; static constexpr auto RING_BUFFER = TraceConfig_BufferConfig_FillPolicy_RING_BUFFER; static constexpr auto DISCARD = TraceConfig_BufferConfig_FillPolicy_DISCARD; static constexpr auto FillPolicy_MIN = TraceConfig_BufferConfig_FillPolicy_UNSPECIFIED; static constexpr auto FillPolicy_MAX = TraceConfig_BufferConfig_FillPolicy_DISCARD; enum FieldNumbers { kSizeKbFieldNumber = 1, kFillPolicyFieldNumber = 4, }; TraceConfig_BufferConfig(); ~TraceConfig_BufferConfig() override; TraceConfig_BufferConfig(TraceConfig_BufferConfig&&) noexcept; TraceConfig_BufferConfig& operator=(TraceConfig_BufferConfig&&); TraceConfig_BufferConfig(const TraceConfig_BufferConfig&); TraceConfig_BufferConfig& operator=(const TraceConfig_BufferConfig&); bool operator==(const TraceConfig_BufferConfig&) const; bool operator!=(const TraceConfig_BufferConfig& other) const { return !(*this == other); } bool ParseFromArray(const void*, size_t) override; std::string SerializeAsString() const override; std::vector SerializeAsArray() const override; void Serialize(::protozero::Message*) const; bool has_size_kb() const { return _has_field_[1]; } uint32_t size_kb() const { return size_kb_; } void set_size_kb(uint32_t value) { size_kb_ = value; _has_field_.set(1); } bool has_fill_policy() const { return _has_field_[4]; } TraceConfig_BufferConfig_FillPolicy fill_policy() const { return fill_policy_; } void set_fill_policy(TraceConfig_BufferConfig_FillPolicy value) { fill_policy_ = value; _has_field_.set(4); } private: uint32_t size_kb_{}; TraceConfig_BufferConfig_FillPolicy fill_policy_{}; // Allows to preserve unknown protobuf fields for compatibility // with future versions of .proto files. std::string unknown_fields_; std::bitset<5> _has_field_{}; }; } // namespace perfetto } // namespace protos } // namespace gen #endif // PERFETTO_PROTOS_PROTOS_PERFETTO_CONFIG_TRACE_CONFIG_PROTO_CPP_H_ /* * Copyright (C) 2017 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_TRACING_CORE_TRACE_CONFIG_H_ #define INCLUDE_PERFETTO_TRACING_CORE_TRACE_CONFIG_H_ // Creates the aliases in the ::perfetto namespace, doing things like: // using ::perfetto::Foo = ::perfetto::protos::gen::Foo. // See comments in forward_decls.h for the historical reasons of this // indirection layer. // gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h" // gen_amalgamated expanded: #include "protos/perfetto/config/trace_config.gen.h" #endif // INCLUDE_PERFETTO_TRACING_CORE_TRACE_CONFIG_H_ // gen_amalgamated begin header: include/perfetto/tracing/data_source.h // gen_amalgamated begin header: include/perfetto/tracing/internal/tracing_muxer.h // gen_amalgamated begin header: include/perfetto/tracing/internal/tracing_tls.h // gen_amalgamated begin header: include/perfetto/tracing/platform.h /* * Copyright (C) 2019 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_TRACING_PLATFORM_H_ #define INCLUDE_PERFETTO_TRACING_PLATFORM_H_ #include #include #include #include #include // gen_amalgamated expanded: #include "perfetto/base/export.h" namespace perfetto { namespace base { class TaskRunner; } // namespace base // This abstract class is used to abstract dependencies on platform-specific // primitives that cannot be implemented by the perfetto codebase and must be // provided or overridden by the embedder. // This is, for instance, for cases where we want to use some particular // base:: class in Chrome and provide instead POSIX fallbacks for other // embedders. // Base class for thread-local objects. This is to get a basic object vtable and // delegate destruction to the embedder. See Platform::CreateThreadLocalObject. class PERFETTO_EXPORT PlatformThreadLocalObject { public: // Implemented by perfetto internal code. The embedder must call this when // implementing GetOrCreateThreadLocalObject() to create an instance for the // first time on each thread. static std::unique_ptr CreateInstance(); virtual ~PlatformThreadLocalObject(); }; class PERFETTO_EXPORT Platform { public: // Embedders can use this unless they have custom needs (e.g. Chrome wanting // to use its own base class for TLS). static Platform* GetDefaultPlatform(); virtual ~Platform(); // Creates a thread-local object. The embedder must: // - Create an instance per-thread calling ThreadLocalObject::CreateInstance. // - Own the lifetime of the returned object as long as the thread is alive. // - Destroy it when the thread exits. // Perfetto requires only one thread-local object overall (obviously, one // instance per-thread) from the embedder. using ThreadLocalObject = ::perfetto::PlatformThreadLocalObject; virtual ThreadLocalObject* GetOrCreateThreadLocalObject() = 0; // Creates a sequenced task runner. The easiest implementation is to create // a new thread (e.g. use base::ThreadTaskRunner) but this can also be // implemented in some more clever way (e.g. using chromiums's scheduler). struct CreateTaskRunnerArgs {}; virtual std::unique_ptr CreateTaskRunner( const CreateTaskRunnerArgs&) = 0; // Used to derive the producer name. Mostly relevant when using the // kSystemBackend mode. It can be an arbitrary string when using the // in-process mode. virtual std::string GetCurrentProcessName() = 0; }; } // namespace perfetto #endif // INCLUDE_PERFETTO_TRACING_PLATFORM_H_ /* * Copyright (C) 2019 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_TLS_H_ #define INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_TLS_H_ #include #include // gen_amalgamated expanded: #include "perfetto/tracing/internal/basic_types.h" // gen_amalgamated expanded: #include "perfetto/tracing/internal/data_source_internal.h" // gen_amalgamated expanded: #include "perfetto/tracing/platform.h" namespace perfetto { class TraceWriterBase; namespace internal { // Organization of the thread-local storage // ---------------------------------------- // First of all, remember the cardinality of the problem: at any point in time // there are M data sources registered (i.e. number of subclasses of DataSource) // and up to N concurrent instances for each data source, so up to M * N total // data source instances around. // Each data source instance can be accessed by T threads (no upper bound). // We can safely put hard limits both to M and N (i.e. say that we support at // most 32 data source types per process and up to 8 concurrent instances). // // We want to make it so from the Platform viewpoint, we use only one global // TLS object, so T instances in total, one per thread, regardless of M and N. // This allows to deal with at-thread-exit destruction only in one place, rather // than N, M or M * N. // // Visually: // [ Thread 1 ] [ Thread 2 ] [ Thread T ] // +---------------+ +---------------+ +---------------+ // Data source Foo | | | | | | // Instance 1 | TLS | | TLS | | TLS | // Instance 2 | Object | | Object | | Object | // Instance 3 | | | | | | // | | | | | | // Data source Bar | | | | | | // Instance 1 | | | | | | // Instance 2 | | | | | | // +---------------+ +---------------+ +---------------+ // // Each TLS Object is organized as an array of M DataSourceThreadLocalState. // Each DSTLS itself is an array of up to N per-instance objects. // The only per-instance object for now is the TraceWriter. // So for each data source, for each instance, for each thread we keep one // TraceWriter. // The lookup is O(1): Given the TLS object, the TraceWriter is just tls[M][N]. class TracingTLS : public Platform::ThreadLocalObject { public: ~TracingTLS() override; // This is checked against TraceMuxerImpl's global generation counter to // handle destruction of TraceWriter(s) that belong to data sources that // have been stopped. When the two numbers diverge, a scan of all the // thread-local TraceWriter(s) is issued. uint32_t generation = 0; // This flag is true while this thread is inside a trace point for any data // source or in other delicate parts of the tracing machinery during which we // should not try to trace. Used to prevent unexpected re-entrancy. bool is_in_trace_point = false; // By default all data source instances have independent thread-local state // (see above). std::array data_sources_tls{}; // Track event data sources, however, share the same thread-local state in // order to be able to share trace writers and interning state across all // track event categories. DataSourceThreadLocalState track_event_tls{}; }; struct ScopedReentrancyAnnotator { ScopedReentrancyAnnotator(TracingTLS& root_tls) : root_tls_(root_tls) { PERFETTO_DCHECK(!root_tls_.is_in_trace_point); root_tls_.is_in_trace_point = true; } ~ScopedReentrancyAnnotator() { root_tls_.is_in_trace_point = false; } private: TracingTLS& root_tls_; }; } // namespace internal } // namespace perfetto #endif // INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_TLS_H_ /* * Copyright (C) 2019 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_MUXER_H_ #define INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_MUXER_H_ #include #include // gen_amalgamated expanded: #include "perfetto/base/export.h" // gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h" // gen_amalgamated expanded: #include "perfetto/tracing/interceptor.h" // gen_amalgamated expanded: #include "perfetto/tracing/internal/basic_types.h" // gen_amalgamated expanded: #include "perfetto/tracing/internal/tracing_tls.h" // gen_amalgamated expanded: #include "perfetto/tracing/platform.h" namespace perfetto { class DataSourceBase; class TraceWriterBase; struct TracingInitArgs; class TracingSession; namespace internal { struct DataSourceStaticState; // This class acts as a bridge between the public API methods and the // TracingBackend(s). It exposes a simplified view of the world to the API // methods, so that they don't have to care about the multiplicity of backends. // It handles all the bookkeeping to map data source instances and trace writers // to the various backends. // See tracing_muxer_impl.h for the full picture. This class contains only the // fewer fields and methods that need to be exposed to public/ headers. Fields // and methods that are required to implement them should go into // src/tracing/internal/tracing_muxer_impl.h instead: that one can pull in // perfetto headers outside of public, this one cannot. class PERFETTO_EXPORT TracingMuxer { public: static TracingMuxer* Get() { return instance_; } virtual ~TracingMuxer(); TracingTLS* GetOrCreateTracingTLS() { return static_cast(platform_->GetOrCreateThreadLocalObject()); } // This method can fail and return false if trying to register more than // kMaxDataSources types. using DataSourceFactory = std::function()>; virtual bool RegisterDataSource(const DataSourceDescriptor&, DataSourceFactory, DataSourceStaticState*) = 0; // It identifies the right backend and forwards the call to it. // The returned TraceWriter must be used within the same sequence (for most // projects this means "same thread"). Alternatively the client needs to take // care of using synchronization primitives to prevent concurrent accesses. virtual std::unique_ptr CreateTraceWriter( DataSourceStaticState*, uint32_t data_source_instance_index, DataSourceState*, BufferExhaustedPolicy buffer_exhausted_policy) = 0; virtual void DestroyStoppedTraceWritersForCurrentThread() = 0; uint32_t generation(std::memory_order ord) { return generation_.load(ord); } using InterceptorFactory = std::function()>; virtual void RegisterInterceptor(const InterceptorDescriptor&, InterceptorFactory, InterceptorBase::TLSFactory, InterceptorBase::TracePacketCallback) = 0; protected: explicit TracingMuxer(Platform* platform) : platform_(platform) {} static TracingMuxer* instance_; Platform* const platform_ = nullptr; // Incremented every time a data source is destroyed. See tracing_tls.h. std::atomic generation_{}; }; } // namespace internal } // namespace perfetto #endif // INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_MUXER_H_ // gen_amalgamated begin header: gen/protos/perfetto/trace/trace_packet.pbzero.h // Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT. #ifndef PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACE_PACKET_PROTO_H_ #define PERFETTO_PROTOS_PROTOS_PERFETTO_TRACE_TRACE_PACKET_PROTO_H_ #include #include // gen_amalgamated expanded: #include "perfetto/protozero/field_writer.h" // gen_amalgamated expanded: #include "perfetto/protozero/message.h" // gen_amalgamated expanded: #include "perfetto/protozero/packed_repeated_fields.h" // gen_amalgamated expanded: #include "perfetto/protozero/proto_decoder.h" // gen_amalgamated expanded: #include "perfetto/protozero/proto_utils.h" namespace perfetto { namespace protos { namespace pbzero { class AndroidEnergyEstimationBreakdown; class AndroidLogPacket; class BatteryCounters; class ChromeBenchmarkMetadata; class ChromeEventBundle; class ChromeMetadataPacket; class ClockSnapshot; class CpuInfo; class DeobfuscationMapping; class ExtensionDescriptor; class FrameTimelineEvent; class FtraceEventBundle; class FtraceStats; class GpuCounterEvent; class GpuLog; class GpuMemTotalEvent; class GpuRenderStageEvent; class GraphicsFrameEvent; class HeapGraph; class InitialDisplayState; class InodeFileMap; class InternedData; class MemoryTrackerSnapshot; class ModuleSymbols; class PackagesList; class PerfSample; class PerfettoMetatrace; class PowerRails; class ProcessDescriptor; class ProcessStats; class ProcessTree; class ProfilePacket; class ProfiledFrameSymbols; class SmapsPacket; class StreamingAllocation; class StreamingFree; class StreamingProfilePacket; class SysStats; class SystemInfo; class TestEvent; class ThreadDescriptor; class TraceConfig; class TracePacketDefaults; class TraceStats; class TracingServiceEvent; class TrackDescriptor; class TrackEvent; class Trigger; class UiState; class VulkanApiEvent; class VulkanMemoryEvent; enum TracePacket_SequenceFlags : int32_t { TracePacket_SequenceFlags_SEQ_UNSPECIFIED = 0, TracePacket_SequenceFlags_SEQ_INCREMENTAL_STATE_CLEARED = 1, TracePacket_SequenceFlags_SEQ_NEEDS_INCREMENTAL_STATE = 2, }; const TracePacket_SequenceFlags TracePacket_SequenceFlags_MIN = TracePacket_SequenceFlags_SEQ_UNSPECIFIED; const TracePacket_SequenceFlags TracePacket_SequenceFlags_MAX = TracePacket_SequenceFlags_SEQ_NEEDS_INCREMENTAL_STATE; class TracePacket_Decoder : public ::protozero::TypedProtoDecoder { public: TracePacket_Decoder(const uint8_t* data, size_t len) : TypedProtoDecoder(data, len) {} explicit TracePacket_Decoder(const std::string& raw) : TypedProtoDecoder(reinterpret_cast(raw.data()), raw.size()) {} explicit TracePacket_Decoder(const ::protozero::ConstBytes& raw) : TypedProtoDecoder(raw.data, raw.size) {} bool has_timestamp() const { return at<8>().valid(); } uint64_t timestamp() const { return at<8>().as_uint64(); } bool has_timestamp_clock_id() const { return at<58>().valid(); } uint32_t timestamp_clock_id() const { return at<58>().as_uint32(); } bool has_process_tree() const { return at<2>().valid(); } ::protozero::ConstBytes process_tree() const { return at<2>().as_bytes(); } bool has_process_stats() const { return at<9>().valid(); } ::protozero::ConstBytes process_stats() const { return at<9>().as_bytes(); } bool has_inode_file_map() const { return at<4>().valid(); } ::protozero::ConstBytes inode_file_map() const { return at<4>().as_bytes(); } bool has_chrome_events() const { return at<5>().valid(); } ::protozero::ConstBytes chrome_events() const { return at<5>().as_bytes(); } bool has_clock_snapshot() const { return at<6>().valid(); } ::protozero::ConstBytes clock_snapshot() const { return at<6>().as_bytes(); } bool has_sys_stats() const { return at<7>().valid(); } ::protozero::ConstBytes sys_stats() const { return at<7>().as_bytes(); } bool has_track_event() const { return at<11>().valid(); } ::protozero::ConstBytes track_event() const { return at<11>().as_bytes(); } bool has_trace_config() const { return at<33>().valid(); } ::protozero::ConstBytes trace_config() const { return at<33>().as_bytes(); } bool has_ftrace_stats() const { return at<34>().valid(); } ::protozero::ConstBytes ftrace_stats() const { return at<34>().as_bytes(); } bool has_trace_stats() const { return at<35>().valid(); } ::protozero::ConstBytes trace_stats() const { return at<35>().as_bytes(); } bool has_profile_packet() const { return at<37>().valid(); } ::protozero::ConstBytes profile_packet() const { return at<37>().as_bytes(); } bool has_streaming_allocation() const { return at<74>().valid(); } ::protozero::ConstBytes streaming_allocation() const { return at<74>().as_bytes(); } bool has_streaming_free() const { return at<75>().valid(); } ::protozero::ConstBytes streaming_free() const { return at<75>().as_bytes(); } bool has_battery() const { return at<38>().valid(); } ::protozero::ConstBytes battery() const { return at<38>().as_bytes(); } bool has_power_rails() const { return at<40>().valid(); } ::protozero::ConstBytes power_rails() const { return at<40>().as_bytes(); } bool has_android_log() const { return at<39>().valid(); } ::protozero::ConstBytes android_log() const { return at<39>().as_bytes(); } bool has_system_info() const { return at<45>().valid(); } ::protozero::ConstBytes system_info() const { return at<45>().as_bytes(); } bool has_trigger() const { return at<46>().valid(); } ::protozero::ConstBytes trigger() const { return at<46>().as_bytes(); } bool has_packages_list() const { return at<47>().valid(); } ::protozero::ConstBytes packages_list() const { return at<47>().as_bytes(); } bool has_chrome_benchmark_metadata() const { return at<48>().valid(); } ::protozero::ConstBytes chrome_benchmark_metadata() const { return at<48>().as_bytes(); } bool has_perfetto_metatrace() const { return at<49>().valid(); } ::protozero::ConstBytes perfetto_metatrace() const { return at<49>().as_bytes(); } bool has_chrome_metadata() const { return at<51>().valid(); } ::protozero::ConstBytes chrome_metadata() const { return at<51>().as_bytes(); } bool has_gpu_counter_event() const { return at<52>().valid(); } ::protozero::ConstBytes gpu_counter_event() const { return at<52>().as_bytes(); } bool has_gpu_render_stage_event() const { return at<53>().valid(); } ::protozero::ConstBytes gpu_render_stage_event() const { return at<53>().as_bytes(); } bool has_streaming_profile_packet() const { return at<54>().valid(); } ::protozero::ConstBytes streaming_profile_packet() const { return at<54>().as_bytes(); } bool has_heap_graph() const { return at<56>().valid(); } ::protozero::ConstBytes heap_graph() const { return at<56>().as_bytes(); } bool has_graphics_frame_event() const { return at<57>().valid(); } ::protozero::ConstBytes graphics_frame_event() const { return at<57>().as_bytes(); } bool has_vulkan_memory_event() const { return at<62>().valid(); } ::protozero::ConstBytes vulkan_memory_event() const { return at<62>().as_bytes(); } bool has_gpu_log() const { return at<63>().valid(); } ::protozero::ConstBytes gpu_log() const { return at<63>().as_bytes(); } bool has_vulkan_api_event() const { return at<65>().valid(); } ::protozero::ConstBytes vulkan_api_event() const { return at<65>().as_bytes(); } bool has_perf_sample() const { return at<66>().valid(); } ::protozero::ConstBytes perf_sample() const { return at<66>().as_bytes(); } bool has_cpu_info() const { return at<67>().valid(); } ::protozero::ConstBytes cpu_info() const { return at<67>().as_bytes(); } bool has_smaps_packet() const { return at<68>().valid(); } ::protozero::ConstBytes smaps_packet() const { return at<68>().as_bytes(); } bool has_service_event() const { return at<69>().valid(); } ::protozero::ConstBytes service_event() const { return at<69>().as_bytes(); } bool has_initial_display_state() const { return at<70>().valid(); } ::protozero::ConstBytes initial_display_state() const { return at<70>().as_bytes(); } bool has_gpu_mem_total_event() const { return at<71>().valid(); } ::protozero::ConstBytes gpu_mem_total_event() const { return at<71>().as_bytes(); } bool has_memory_tracker_snapshot() const { return at<73>().valid(); } ::protozero::ConstBytes memory_tracker_snapshot() const { return at<73>().as_bytes(); } bool has_frame_timeline_event() const { return at<76>().valid(); } ::protozero::ConstBytes frame_timeline_event() const { return at<76>().as_bytes(); } bool has_android_energy_estimation_breakdown() const { return at<77>().valid(); } ::protozero::ConstBytes android_energy_estimation_breakdown() const { return at<77>().as_bytes(); } bool has_ui_state() const { return at<78>().valid(); } ::protozero::ConstBytes ui_state() const { return at<78>().as_bytes(); } bool has_profiled_frame_symbols() const { return at<55>().valid(); } ::protozero::ConstBytes profiled_frame_symbols() const { return at<55>().as_bytes(); } bool has_module_symbols() const { return at<61>().valid(); } ::protozero::ConstBytes module_symbols() const { return at<61>().as_bytes(); } bool has_deobfuscation_mapping() const { return at<64>().valid(); } ::protozero::ConstBytes deobfuscation_mapping() const { return at<64>().as_bytes(); } bool has_track_descriptor() const { return at<60>().valid(); } ::protozero::ConstBytes track_descriptor() const { return at<60>().as_bytes(); } bool has_process_descriptor() const { return at<43>().valid(); } ::protozero::ConstBytes process_descriptor() const { return at<43>().as_bytes(); } bool has_thread_descriptor() const { return at<44>().valid(); } ::protozero::ConstBytes thread_descriptor() const { return at<44>().as_bytes(); } bool has_ftrace_events() const { return at<1>().valid(); } ::protozero::ConstBytes ftrace_events() const { return at<1>().as_bytes(); } bool has_synchronization_marker() const { return at<36>().valid(); } ::protozero::ConstBytes synchronization_marker() const { return at<36>().as_bytes(); } bool has_compressed_packets() const { return at<50>().valid(); } ::protozero::ConstBytes compressed_packets() const { return at<50>().as_bytes(); } bool has_extension_descriptor() const { return at<72>().valid(); } ::protozero::ConstBytes extension_descriptor() const { return at<72>().as_bytes(); } bool has_for_testing() const { return at<900>().valid(); } ::protozero::ConstBytes for_testing() const { return at<900>().as_bytes(); } bool has_trusted_uid() const { return at<3>().valid(); } int32_t trusted_uid() const { return at<3>().as_int32(); } bool has_trusted_packet_sequence_id() const { return at<10>().valid(); } uint32_t trusted_packet_sequence_id() const { return at<10>().as_uint32(); } bool has_interned_data() const { return at<12>().valid(); } ::protozero::ConstBytes interned_data() const { return at<12>().as_bytes(); } bool has_sequence_flags() const { return at<13>().valid(); } uint32_t sequence_flags() const { return at<13>().as_uint32(); } bool has_incremental_state_cleared() const { return at<41>().valid(); } bool incremental_state_cleared() const { return at<41>().as_bool(); } bool has_trace_packet_defaults() const { return at<59>().valid(); } ::protozero::ConstBytes trace_packet_defaults() const { return at<59>().as_bytes(); } bool has_previous_packet_dropped() const { return at<42>().valid(); } bool previous_packet_dropped() const { return at<42>().as_bool(); } }; class TracePacket : public ::protozero::Message { public: using Decoder = TracePacket_Decoder; enum : int32_t { kTimestampFieldNumber = 8, kTimestampClockIdFieldNumber = 58, kProcessTreeFieldNumber = 2, kProcessStatsFieldNumber = 9, kInodeFileMapFieldNumber = 4, kChromeEventsFieldNumber = 5, kClockSnapshotFieldNumber = 6, kSysStatsFieldNumber = 7, kTrackEventFieldNumber = 11, kTraceConfigFieldNumber = 33, kFtraceStatsFieldNumber = 34, kTraceStatsFieldNumber = 35, kProfilePacketFieldNumber = 37, kStreamingAllocationFieldNumber = 74, kStreamingFreeFieldNumber = 75, kBatteryFieldNumber = 38, kPowerRailsFieldNumber = 40, kAndroidLogFieldNumber = 39, kSystemInfoFieldNumber = 45, kTriggerFieldNumber = 46, kPackagesListFieldNumber = 47, kChromeBenchmarkMetadataFieldNumber = 48, kPerfettoMetatraceFieldNumber = 49, kChromeMetadataFieldNumber = 51, kGpuCounterEventFieldNumber = 52, kGpuRenderStageEventFieldNumber = 53, kStreamingProfilePacketFieldNumber = 54, kHeapGraphFieldNumber = 56, kGraphicsFrameEventFieldNumber = 57, kVulkanMemoryEventFieldNumber = 62, kGpuLogFieldNumber = 63, kVulkanApiEventFieldNumber = 65, kPerfSampleFieldNumber = 66, kCpuInfoFieldNumber = 67, kSmapsPacketFieldNumber = 68, kServiceEventFieldNumber = 69, kInitialDisplayStateFieldNumber = 70, kGpuMemTotalEventFieldNumber = 71, kMemoryTrackerSnapshotFieldNumber = 73, kFrameTimelineEventFieldNumber = 76, kAndroidEnergyEstimationBreakdownFieldNumber = 77, kUiStateFieldNumber = 78, kProfiledFrameSymbolsFieldNumber = 55, kModuleSymbolsFieldNumber = 61, kDeobfuscationMappingFieldNumber = 64, kTrackDescriptorFieldNumber = 60, kProcessDescriptorFieldNumber = 43, kThreadDescriptorFieldNumber = 44, kFtraceEventsFieldNumber = 1, kSynchronizationMarkerFieldNumber = 36, kCompressedPacketsFieldNumber = 50, kExtensionDescriptorFieldNumber = 72, kForTestingFieldNumber = 900, kTrustedUidFieldNumber = 3, kTrustedPacketSequenceIdFieldNumber = 10, kInternedDataFieldNumber = 12, kSequenceFlagsFieldNumber = 13, kIncrementalStateClearedFieldNumber = 41, kTracePacketDefaultsFieldNumber = 59, kPreviousPacketDroppedFieldNumber = 42, }; using SequenceFlags = ::perfetto::protos::pbzero::TracePacket_SequenceFlags; static const SequenceFlags SEQ_UNSPECIFIED = TracePacket_SequenceFlags_SEQ_UNSPECIFIED; static const SequenceFlags SEQ_INCREMENTAL_STATE_CLEARED = TracePacket_SequenceFlags_SEQ_INCREMENTAL_STATE_CLEARED; static const SequenceFlags SEQ_NEEDS_INCREMENTAL_STATE = TracePacket_SequenceFlags_SEQ_NEEDS_INCREMENTAL_STATE; using FieldMetadata_Timestamp = ::protozero::proto_utils::FieldMetadata< 8, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kUint64, uint64_t, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_Timestamp kTimestamp() { return {}; } void set_timestamp(uint64_t value) { static constexpr uint32_t field_id = FieldMetadata_Timestamp::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kUint64> ::Append(*this, field_id, value); } using FieldMetadata_TimestampClockId = ::protozero::proto_utils::FieldMetadata< 58, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kUint32, uint32_t, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_TimestampClockId kTimestampClockId() { return {}; } void set_timestamp_clock_id(uint32_t value) { static constexpr uint32_t field_id = FieldMetadata_TimestampClockId::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kUint32> ::Append(*this, field_id, value); } using FieldMetadata_ProcessTree = ::protozero::proto_utils::FieldMetadata< 2, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, ProcessTree, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ProcessTree kProcessTree() { return {}; } template T* set_process_tree() { return BeginNestedMessage(2); } using FieldMetadata_ProcessStats = ::protozero::proto_utils::FieldMetadata< 9, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, ProcessStats, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ProcessStats kProcessStats() { return {}; } template T* set_process_stats() { return BeginNestedMessage(9); } using FieldMetadata_InodeFileMap = ::protozero::proto_utils::FieldMetadata< 4, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, InodeFileMap, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_InodeFileMap kInodeFileMap() { return {}; } template T* set_inode_file_map() { return BeginNestedMessage(4); } using FieldMetadata_ChromeEvents = ::protozero::proto_utils::FieldMetadata< 5, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, ChromeEventBundle, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ChromeEvents kChromeEvents() { return {}; } template T* set_chrome_events() { return BeginNestedMessage(5); } using FieldMetadata_ClockSnapshot = ::protozero::proto_utils::FieldMetadata< 6, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, ClockSnapshot, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ClockSnapshot kClockSnapshot() { return {}; } template T* set_clock_snapshot() { return BeginNestedMessage(6); } using FieldMetadata_SysStats = ::protozero::proto_utils::FieldMetadata< 7, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, SysStats, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_SysStats kSysStats() { return {}; } template T* set_sys_stats() { return BeginNestedMessage(7); } using FieldMetadata_TrackEvent = ::protozero::proto_utils::FieldMetadata< 11, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, TrackEvent, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_TrackEvent kTrackEvent() { return {}; } template T* set_track_event() { return BeginNestedMessage(11); } using FieldMetadata_TraceConfig = ::protozero::proto_utils::FieldMetadata< 33, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, TraceConfig, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_TraceConfig kTraceConfig() { return {}; } template T* set_trace_config() { return BeginNestedMessage(33); } using FieldMetadata_FtraceStats = ::protozero::proto_utils::FieldMetadata< 34, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, FtraceStats, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_FtraceStats kFtraceStats() { return {}; } template T* set_ftrace_stats() { return BeginNestedMessage(34); } using FieldMetadata_TraceStats = ::protozero::proto_utils::FieldMetadata< 35, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, TraceStats, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_TraceStats kTraceStats() { return {}; } template T* set_trace_stats() { return BeginNestedMessage(35); } using FieldMetadata_ProfilePacket = ::protozero::proto_utils::FieldMetadata< 37, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, ProfilePacket, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ProfilePacket kProfilePacket() { return {}; } template T* set_profile_packet() { return BeginNestedMessage(37); } using FieldMetadata_StreamingAllocation = ::protozero::proto_utils::FieldMetadata< 74, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, StreamingAllocation, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_StreamingAllocation kStreamingAllocation() { return {}; } template T* set_streaming_allocation() { return BeginNestedMessage(74); } using FieldMetadata_StreamingFree = ::protozero::proto_utils::FieldMetadata< 75, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, StreamingFree, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_StreamingFree kStreamingFree() { return {}; } template T* set_streaming_free() { return BeginNestedMessage(75); } using FieldMetadata_Battery = ::protozero::proto_utils::FieldMetadata< 38, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, BatteryCounters, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_Battery kBattery() { return {}; } template T* set_battery() { return BeginNestedMessage(38); } using FieldMetadata_PowerRails = ::protozero::proto_utils::FieldMetadata< 40, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, PowerRails, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_PowerRails kPowerRails() { return {}; } template T* set_power_rails() { return BeginNestedMessage(40); } using FieldMetadata_AndroidLog = ::protozero::proto_utils::FieldMetadata< 39, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, AndroidLogPacket, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_AndroidLog kAndroidLog() { return {}; } template T* set_android_log() { return BeginNestedMessage(39); } using FieldMetadata_SystemInfo = ::protozero::proto_utils::FieldMetadata< 45, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, SystemInfo, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_SystemInfo kSystemInfo() { return {}; } template T* set_system_info() { return BeginNestedMessage(45); } using FieldMetadata_Trigger = ::protozero::proto_utils::FieldMetadata< 46, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, Trigger, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_Trigger kTrigger() { return {}; } template T* set_trigger() { return BeginNestedMessage(46); } using FieldMetadata_PackagesList = ::protozero::proto_utils::FieldMetadata< 47, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, PackagesList, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_PackagesList kPackagesList() { return {}; } template T* set_packages_list() { return BeginNestedMessage(47); } using FieldMetadata_ChromeBenchmarkMetadata = ::protozero::proto_utils::FieldMetadata< 48, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, ChromeBenchmarkMetadata, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ChromeBenchmarkMetadata kChromeBenchmarkMetadata() { return {}; } template T* set_chrome_benchmark_metadata() { return BeginNestedMessage(48); } using FieldMetadata_PerfettoMetatrace = ::protozero::proto_utils::FieldMetadata< 49, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, PerfettoMetatrace, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_PerfettoMetatrace kPerfettoMetatrace() { return {}; } template T* set_perfetto_metatrace() { return BeginNestedMessage(49); } using FieldMetadata_ChromeMetadata = ::protozero::proto_utils::FieldMetadata< 51, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, ChromeMetadataPacket, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ChromeMetadata kChromeMetadata() { return {}; } template T* set_chrome_metadata() { return BeginNestedMessage(51); } using FieldMetadata_GpuCounterEvent = ::protozero::proto_utils::FieldMetadata< 52, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, GpuCounterEvent, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_GpuCounterEvent kGpuCounterEvent() { return {}; } template T* set_gpu_counter_event() { return BeginNestedMessage(52); } using FieldMetadata_GpuRenderStageEvent = ::protozero::proto_utils::FieldMetadata< 53, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, GpuRenderStageEvent, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_GpuRenderStageEvent kGpuRenderStageEvent() { return {}; } template T* set_gpu_render_stage_event() { return BeginNestedMessage(53); } using FieldMetadata_StreamingProfilePacket = ::protozero::proto_utils::FieldMetadata< 54, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, StreamingProfilePacket, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_StreamingProfilePacket kStreamingProfilePacket() { return {}; } template T* set_streaming_profile_packet() { return BeginNestedMessage(54); } using FieldMetadata_HeapGraph = ::protozero::proto_utils::FieldMetadata< 56, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, HeapGraph, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_HeapGraph kHeapGraph() { return {}; } template T* set_heap_graph() { return BeginNestedMessage(56); } using FieldMetadata_GraphicsFrameEvent = ::protozero::proto_utils::FieldMetadata< 57, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, GraphicsFrameEvent, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_GraphicsFrameEvent kGraphicsFrameEvent() { return {}; } template T* set_graphics_frame_event() { return BeginNestedMessage(57); } using FieldMetadata_VulkanMemoryEvent = ::protozero::proto_utils::FieldMetadata< 62, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, VulkanMemoryEvent, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_VulkanMemoryEvent kVulkanMemoryEvent() { return {}; } template T* set_vulkan_memory_event() { return BeginNestedMessage(62); } using FieldMetadata_GpuLog = ::protozero::proto_utils::FieldMetadata< 63, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, GpuLog, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_GpuLog kGpuLog() { return {}; } template T* set_gpu_log() { return BeginNestedMessage(63); } using FieldMetadata_VulkanApiEvent = ::protozero::proto_utils::FieldMetadata< 65, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, VulkanApiEvent, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_VulkanApiEvent kVulkanApiEvent() { return {}; } template T* set_vulkan_api_event() { return BeginNestedMessage(65); } using FieldMetadata_PerfSample = ::protozero::proto_utils::FieldMetadata< 66, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, PerfSample, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_PerfSample kPerfSample() { return {}; } template T* set_perf_sample() { return BeginNestedMessage(66); } using FieldMetadata_CpuInfo = ::protozero::proto_utils::FieldMetadata< 67, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, CpuInfo, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_CpuInfo kCpuInfo() { return {}; } template T* set_cpu_info() { return BeginNestedMessage(67); } using FieldMetadata_SmapsPacket = ::protozero::proto_utils::FieldMetadata< 68, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, SmapsPacket, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_SmapsPacket kSmapsPacket() { return {}; } template T* set_smaps_packet() { return BeginNestedMessage(68); } using FieldMetadata_ServiceEvent = ::protozero::proto_utils::FieldMetadata< 69, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, TracingServiceEvent, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ServiceEvent kServiceEvent() { return {}; } template T* set_service_event() { return BeginNestedMessage(69); } using FieldMetadata_InitialDisplayState = ::protozero::proto_utils::FieldMetadata< 70, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, InitialDisplayState, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_InitialDisplayState kInitialDisplayState() { return {}; } template T* set_initial_display_state() { return BeginNestedMessage(70); } using FieldMetadata_GpuMemTotalEvent = ::protozero::proto_utils::FieldMetadata< 71, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, GpuMemTotalEvent, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_GpuMemTotalEvent kGpuMemTotalEvent() { return {}; } template T* set_gpu_mem_total_event() { return BeginNestedMessage(71); } using FieldMetadata_MemoryTrackerSnapshot = ::protozero::proto_utils::FieldMetadata< 73, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, MemoryTrackerSnapshot, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_MemoryTrackerSnapshot kMemoryTrackerSnapshot() { return {}; } template T* set_memory_tracker_snapshot() { return BeginNestedMessage(73); } using FieldMetadata_FrameTimelineEvent = ::protozero::proto_utils::FieldMetadata< 76, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, FrameTimelineEvent, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_FrameTimelineEvent kFrameTimelineEvent() { return {}; } template T* set_frame_timeline_event() { return BeginNestedMessage(76); } using FieldMetadata_AndroidEnergyEstimationBreakdown = ::protozero::proto_utils::FieldMetadata< 77, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, AndroidEnergyEstimationBreakdown, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_AndroidEnergyEstimationBreakdown kAndroidEnergyEstimationBreakdown() { return {}; } template T* set_android_energy_estimation_breakdown() { return BeginNestedMessage(77); } using FieldMetadata_UiState = ::protozero::proto_utils::FieldMetadata< 78, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, UiState, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_UiState kUiState() { return {}; } template T* set_ui_state() { return BeginNestedMessage(78); } using FieldMetadata_ProfiledFrameSymbols = ::protozero::proto_utils::FieldMetadata< 55, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, ProfiledFrameSymbols, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ProfiledFrameSymbols kProfiledFrameSymbols() { return {}; } template T* set_profiled_frame_symbols() { return BeginNestedMessage(55); } using FieldMetadata_ModuleSymbols = ::protozero::proto_utils::FieldMetadata< 61, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, ModuleSymbols, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ModuleSymbols kModuleSymbols() { return {}; } template T* set_module_symbols() { return BeginNestedMessage(61); } using FieldMetadata_DeobfuscationMapping = ::protozero::proto_utils::FieldMetadata< 64, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, DeobfuscationMapping, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_DeobfuscationMapping kDeobfuscationMapping() { return {}; } template T* set_deobfuscation_mapping() { return BeginNestedMessage(64); } using FieldMetadata_TrackDescriptor = ::protozero::proto_utils::FieldMetadata< 60, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, TrackDescriptor, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_TrackDescriptor kTrackDescriptor() { return {}; } template T* set_track_descriptor() { return BeginNestedMessage(60); } using FieldMetadata_ProcessDescriptor = ::protozero::proto_utils::FieldMetadata< 43, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, ProcessDescriptor, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ProcessDescriptor kProcessDescriptor() { return {}; } template T* set_process_descriptor() { return BeginNestedMessage(43); } using FieldMetadata_ThreadDescriptor = ::protozero::proto_utils::FieldMetadata< 44, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, ThreadDescriptor, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ThreadDescriptor kThreadDescriptor() { return {}; } template T* set_thread_descriptor() { return BeginNestedMessage(44); } using FieldMetadata_FtraceEvents = ::protozero::proto_utils::FieldMetadata< 1, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, FtraceEventBundle, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_FtraceEvents kFtraceEvents() { return {}; } template T* set_ftrace_events() { return BeginNestedMessage(1); } using FieldMetadata_SynchronizationMarker = ::protozero::proto_utils::FieldMetadata< 36, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kBytes, std::string, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_SynchronizationMarker kSynchronizationMarker() { return {}; } void set_synchronization_marker(const uint8_t* data, size_t size) { AppendBytes(FieldMetadata_SynchronizationMarker::kFieldId, data, size); } void set_synchronization_marker(std::string value) { static constexpr uint32_t field_id = FieldMetadata_SynchronizationMarker::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kBytes> ::Append(*this, field_id, value); } using FieldMetadata_CompressedPackets = ::protozero::proto_utils::FieldMetadata< 50, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kBytes, std::string, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_CompressedPackets kCompressedPackets() { return {}; } void set_compressed_packets(const uint8_t* data, size_t size) { AppendBytes(FieldMetadata_CompressedPackets::kFieldId, data, size); } void set_compressed_packets(std::string value) { static constexpr uint32_t field_id = FieldMetadata_CompressedPackets::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kBytes> ::Append(*this, field_id, value); } using FieldMetadata_ExtensionDescriptor = ::protozero::proto_utils::FieldMetadata< 72, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, ExtensionDescriptor, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ExtensionDescriptor kExtensionDescriptor() { return {}; } template T* set_extension_descriptor() { return BeginNestedMessage(72); } using FieldMetadata_ForTesting = ::protozero::proto_utils::FieldMetadata< 900, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, TestEvent, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_ForTesting kForTesting() { return {}; } template T* set_for_testing() { return BeginNestedMessage(900); } using FieldMetadata_TrustedUid = ::protozero::proto_utils::FieldMetadata< 3, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kInt32, int32_t, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_TrustedUid kTrustedUid() { return {}; } void set_trusted_uid(int32_t value) { static constexpr uint32_t field_id = FieldMetadata_TrustedUid::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kInt32> ::Append(*this, field_id, value); } using FieldMetadata_TrustedPacketSequenceId = ::protozero::proto_utils::FieldMetadata< 10, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kUint32, uint32_t, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_TrustedPacketSequenceId kTrustedPacketSequenceId() { return {}; } void set_trusted_packet_sequence_id(uint32_t value) { static constexpr uint32_t field_id = FieldMetadata_TrustedPacketSequenceId::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kUint32> ::Append(*this, field_id, value); } using FieldMetadata_InternedData = ::protozero::proto_utils::FieldMetadata< 12, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, InternedData, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_InternedData kInternedData() { return {}; } template T* set_interned_data() { return BeginNestedMessage(12); } using FieldMetadata_SequenceFlags = ::protozero::proto_utils::FieldMetadata< 13, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kUint32, uint32_t, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_SequenceFlags kSequenceFlags() { return {}; } void set_sequence_flags(uint32_t value) { static constexpr uint32_t field_id = FieldMetadata_SequenceFlags::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kUint32> ::Append(*this, field_id, value); } using FieldMetadata_IncrementalStateCleared = ::protozero::proto_utils::FieldMetadata< 41, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kBool, bool, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_IncrementalStateCleared kIncrementalStateCleared() { return {}; } void set_incremental_state_cleared(bool value) { static constexpr uint32_t field_id = FieldMetadata_IncrementalStateCleared::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kBool> ::Append(*this, field_id, value); } using FieldMetadata_TracePacketDefaults = ::protozero::proto_utils::FieldMetadata< 59, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kMessage, TracePacketDefaults, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_TracePacketDefaults kTracePacketDefaults() { return {}; } template T* set_trace_packet_defaults() { return BeginNestedMessage(59); } using FieldMetadata_PreviousPacketDropped = ::protozero::proto_utils::FieldMetadata< 42, ::protozero::proto_utils::RepetitionType::kNotRepeated, ::protozero::proto_utils::ProtoSchemaType::kBool, bool, TracePacket>; // Ceci n'est pas une pipe. // This is actually a variable of FieldMetadataHelper> // type (and users are expected to use it as such, hence kCamelCase name). // It is declared as a function to keep protozero bindings header-only as // inline constexpr variables are not available until C++17 (while inline // functions are). // TODO(altimin): Use inline variable instead after adopting C++17. static constexpr FieldMetadata_PreviousPacketDropped kPreviousPacketDropped() { return {}; } void set_previous_packet_dropped(bool value) { static constexpr uint32_t field_id = FieldMetadata_PreviousPacketDropped::kFieldId; // Call the appropriate protozero::Message::Append(field_id, ...) // method based on the type of the field. ::protozero::internal::FieldWriter< ::protozero::proto_utils::ProtoSchemaType::kBool> ::Append(*this, field_id, value); } }; } // Namespace. } // Namespace. } // Namespace. #endif // Include guard. /* * Copyright (C) 2019 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_TRACING_DATA_SOURCE_H_ #define INCLUDE_PERFETTO_TRACING_DATA_SOURCE_H_ // This header contains the key class (DataSource) that a producer app should // override in order to create a custom data source that gets tracing Start/Stop // notifications and emits tracing data. #include #include #include #include #include #include #include #include // gen_amalgamated expanded: #include "perfetto/base/build_config.h" // gen_amalgamated expanded: #include "perfetto/base/compiler.h" // gen_amalgamated expanded: #include "perfetto/base/export.h" // gen_amalgamated expanded: #include "perfetto/protozero/message.h" // gen_amalgamated expanded: #include "perfetto/protozero/message_handle.h" // gen_amalgamated expanded: #include "perfetto/tracing/buffer_exhausted_policy.h" // gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h" // gen_amalgamated expanded: #include "perfetto/tracing/internal/basic_types.h" // gen_amalgamated expanded: #include "perfetto/tracing/internal/data_source_internal.h" // gen_amalgamated expanded: #include "perfetto/tracing/internal/tracing_muxer.h" // gen_amalgamated expanded: #include "perfetto/tracing/locked_handle.h" // gen_amalgamated expanded: #include "perfetto/tracing/trace_writer_base.h" // gen_amalgamated expanded: #include "protos/perfetto/trace/trace_packet.pbzero.h" // PERFETTO_COMPONENT_EXPORT is used to mark symbols in Perfetto's headers // (typically templates) that are defined by the user outside of Perfetto and // should be made visible outside the current module. (e.g., in Chrome's // component build). #if !defined(PERFETTO_COMPONENT_EXPORT) #define PERFETTO_COMPONENT_EXPORT #endif namespace perfetto { namespace internal { class TracingMuxerImpl; class TrackEventCategoryRegistry; template class TrackEventDataSource; } // namespace internal // Base class with the virtual methods to get start/stop notifications. // Embedders are supposed to derive the templated version below, not this one. class PERFETTO_EXPORT DataSourceBase { public: virtual ~DataSourceBase(); // TODO(primiano): change the const& args below to be pointers instead. It // makes it more awkward to handle output arguments and require mutable(s). // This requires synchronizing a breaking API change for existing embedders. // OnSetup() is invoked when tracing is configured. In most cases this happens // just before starting the trace. In the case of deferred start (see // deferred_start in trace_config.proto) start might happen later. class SetupArgs { public: // This is valid only within the scope of the OnSetup() call and must not // be retained. const DataSourceConfig* config = nullptr; // The index of this data source instance (0..kMaxDataSourceInstances - 1). uint32_t internal_instance_index = 0; }; virtual void OnSetup(const SetupArgs&); class StartArgs { public: // The index of this data source instance (0..kMaxDataSourceInstances - 1). uint32_t internal_instance_index = 0; }; virtual void OnStart(const StartArgs&); class StopArgs { public: virtual ~StopArgs(); // HandleAsynchronously() can optionally be called to defer the tracing // session stop and write tracing data just before stopping. // This function returns a closure that must be invoked after the last // trace events have been emitted. The returned closure can be called from // any thread. The caller also needs to explicitly call TraceContext.Flush() // from the last Trace() lambda invocation because no other implicit flushes // will happen after the stop signal. // When this function is called, the tracing service will defer the stop of // the tracing session until the returned closure is invoked. // However, the caller cannot hang onto this closure for too long. The // tracing service will forcefully stop the tracing session without waiting // for pending producers after TraceConfig.data_source_stop_timeout_ms // (default: 5s, can be overridden by Consumers when starting a trace). // If the closure is called after this timeout an error will be logged and // the trace data emitted will not be present in the trace. No other // functional side effects (e.g. crashes or corruptions) will happen. In // other words, it is fine to accidentally hold onto this closure for too // long but, if that happens, some tracing data will be lost. virtual std::function HandleStopAsynchronously() const = 0; // The index of this data source instance (0..kMaxDataSourceInstances - 1). uint32_t internal_instance_index = 0; }; virtual void OnStop(const StopArgs&); }; struct DefaultDataSourceTraits { // |IncrementalStateType| can optionally be used store custom per-sequence // incremental data (e.g., interning tables). It should have a Clear() method // for when incremental state needs to be cleared. See // TraceContext::GetIncrementalState(). using IncrementalStateType = void; // Allows overriding what type of thread-local state configuration the data // source uses. By default every data source gets independent thread-local // state, which means every instance uses separate trace writers and // incremental state even on the same thread. Some data sources (most notably // the track event data source) want to share trace writers and incremental // state on the same thread. static internal::DataSourceThreadLocalState* GetDataSourceTLS( internal::DataSourceStaticState* static_state, internal::TracingTLS* root_tls) { auto* ds_tls = &root_tls->data_sources_tls[static_state->index]; // The per-type TLS is either zero-initialized or must have been initialized // for this specific data source type. assert(!ds_tls->static_state || ds_tls->static_state->index == static_state->index); return ds_tls; } }; // Templated base class meant to be derived by embedders to create a custom data // source. DataSourceType must be the type of the derived class itself, e.g.: // class MyDataSource : public DataSourceBase {...}. // // |DataSourceTraits| allows customizing the behavior of the data source. See // |DefaultDataSourceTraits|. template class DataSource : public DataSourceBase { struct DefaultTracePointTraits; public: // The BufferExhaustedPolicy to use for TraceWriters of this DataSource. // Override this in your DataSource class to change the default, which is to // drop data on shared memory overruns. constexpr static BufferExhaustedPolicy kBufferExhaustedPolicy = BufferExhaustedPolicy::kDrop; // Argument passed to the lambda function passed to Trace() (below). class TraceContext { public: using TracePacketHandle = ::protozero::MessageHandle<::perfetto::protos::pbzero::TracePacket>; TraceContext(TraceContext&&) noexcept = default; ~TraceContext() { // If the data source is being intercepted, flush the trace writer after // each trace point to make sure the interceptor sees the data right away. if (PERFETTO_UNLIKELY(tls_inst_->is_intercepted)) Flush(); } TracePacketHandle NewTracePacket() { return tls_inst_->trace_writer->NewTracePacket(); } // Forces a commit of the thread-local tracing data written so far to the // service. This is almost never required (tracing data is periodically // committed as trace pages are filled up) and has a non-negligible // performance hit (requires an IPC + refresh of the current thread-local // chunk). The only case when this should be used is when handling OnStop() // asynchronously, to ensure sure that the data is committed before the // Stop timeout expires. // The TracePacketHandle obtained by the last NewTracePacket() call must be // finalized before calling Flush() (either implicitly by going out of scope // or by explicitly calling Finalize()). // |cb| is an optional callback. When non-null it will request the // service to ACK the flush and will be invoked on an internal thread after // the service has acknowledged it. The callback might be NEVER INVOKED if // the service crashes or the IPC connection is dropped. void Flush(std::function cb = {}) { tls_inst_->trace_writer->Flush(cb); } // Returns the number of bytes written on the current thread by the current // data-source since its creation. // This can be useful for splitting protos that might grow very large. uint64_t written() { return tls_inst_->trace_writer->written(); } // Returns a RAII handle to access the data source instance, guaranteeing // that it won't be deleted on another thread (because of trace stopping) // while accessing it from within the Trace() lambda. // The returned handle can be invalid (nullptr) if tracing is stopped // immediately before calling this. The caller is supposed to check for its // validity before using it. After checking, the handle is guaranteed to // remain valid until the handle goes out of scope. LockedHandle GetDataSourceLocked() { auto* internal_state = static_state_.TryGet(instance_index_); if (!internal_state) return LockedHandle(); return LockedHandle( &internal_state->lock, static_cast(internal_state->data_source.get())); } typename DataSourceTraits::IncrementalStateType* GetIncrementalState() { // Recreate incremental state data if it has been reset by the service. if (tls_inst_->incremental_state_generation != static_state_.incremental_state_generation.load( std::memory_order_relaxed)) { tls_inst_->incremental_state.reset(); CreateIncrementalState(tls_inst_); } return reinterpret_cast( tls_inst_->incremental_state.get()); } private: friend class DataSource; template friend class internal::TrackEventDataSource; TraceContext(internal::DataSourceInstanceThreadLocalState* tls_inst, uint32_t instance_index) : tls_inst_(tls_inst), instance_index_(instance_index) {} TraceContext(const TraceContext&) = delete; TraceContext& operator=(const TraceContext&) = delete; internal::DataSourceInstanceThreadLocalState* const tls_inst_; uint32_t const instance_index_; }; // The main tracing method. Tracing code should call this passing a lambda as // argument, with the following signature: void(TraceContext). // The lambda will be called synchronously (i.e., always before Trace() // returns) only if tracing is enabled and the data source has been enabled in // the tracing config. // The lambda can be called more than once per Trace() call, in the case of // concurrent tracing sessions (or even if the data source is instantiated // twice within the same trace config). template static void Trace(Lambda tracing_fn) { CallIfEnabled([&tracing_fn](uint32_t instances) { TraceWithInstances(instances, std::move(tracing_fn)); }); } // An efficient trace point guard for checking if this data source is active. // |callback| is a function which will only be called if there are active // instances. It is given an instance state parameter, which should be passed // to TraceWithInstances() to actually record trace data. template static void CallIfEnabled(Callback callback, typename Traits::TracePointData trace_point_data = {}) PERFETTO_ALWAYS_INLINE { // |instances| is a per-class bitmap that tells: // 1. If the data source is enabled at all. // 2. The index of the slot within |static_state_| that holds the instance // state. In turn this allows to map the data source to the tracing // session and buffers. // memory_order_relaxed is okay because: // - |instances| is re-read with an acquire barrier below if this succeeds. // - The code between this point and the acquire-load is based on static // storage which has indefinite lifetime. uint32_t instances = Traits::GetActiveInstances(trace_point_data) ->load(std::memory_order_relaxed); // This is the tracing fast-path. Bail out immediately if tracing is not // enabled (or tracing is enabled but not for this data source). if (PERFETTO_LIKELY(!instances)) return; callback(instances); } // The "lower half" of a trace point which actually performs tracing after // this data source has been determined to be active. // |instances| must be the instance state value retrieved through // CallIfEnabled(). // |tracing_fn| will be called to record trace data as in Trace(). // // |trace_point_data| is an optional parameter given to |Traits:: // GetActiveInstances| to make it possible to use custom storage for // the data source enabled state. This is, for example, used by TrackEvent to // implement per-tracing category enabled states. // // TODO(primiano): all the stuff below should be outlined from the trace // point. Or at least we should have some compile-time traits like // kOptimizeBinarySize / kOptimizeTracingLatency. template static void TraceWithInstances( uint32_t instances, Lambda tracing_fn, typename Traits::TracePointData trace_point_data = {}) { PERFETTO_DCHECK(instances); constexpr auto kMaxDataSourceInstances = internal::kMaxDataSourceInstances; // See tracing_muxer.h for the structure of the TLS. auto* tracing_impl = internal::TracingMuxer::Get(); if (PERFETTO_UNLIKELY(!tls_state_)) tls_state_ = GetOrCreateDataSourceTLS(&static_state_); // Avoid re-entering the trace point recursively. if (PERFETTO_UNLIKELY(tls_state_->root_tls->is_in_trace_point)) return; internal::ScopedReentrancyAnnotator scoped_annotator(*tls_state_->root_tls); // TracingTLS::generation is a global monotonic counter that is incremented // every time a tracing session is stopped. We use that as a signal to force // a slow-path garbage collection of all the trace writers for the current // thread and to destroy the ones that belong to tracing sessions that have // ended. This is to avoid having too many TraceWriter instances alive, each // holding onto one chunk of the shared memory buffer. // Rationale why memory_order_relaxed should be fine: // - The TraceWriter object that we use is always constructed and destructed // on the current thread. There is no risk of accessing a half-initialized // TraceWriter (which would be really bad). // - In the worst case, in the case of a race on the generation check, we // might end up using a TraceWriter for the same data source that belongs // to a stopped session. This is not really wrong, as we don't give any // guarantee on the global atomicity of the stop. In the worst case the // service will reject the data commit if this arrives too late. if (PERFETTO_UNLIKELY( tls_state_->root_tls->generation != tracing_impl->generation(std::memory_order_relaxed))) { // Will update root_tls->generation. tracing_impl->DestroyStoppedTraceWritersForCurrentThread(); } for (uint32_t i = 0; i < kMaxDataSourceInstances; i++) { internal::DataSourceState* instance_state = static_state_.TryGetCached(instances, i); if (!instance_state) continue; // Even if we passed the check above, the DataSourceInstance might be // still destroyed concurrently while this code runs. The code below is // designed to deal with such race, as follows: // - We don't access the user-defined data source instance state. The only // bits of state we use are |backend_id| and |buffer_id|. // - Beyond those two integers, we access only the TraceWriter here. The // TraceWriter is always safe because it lives on the TLS. // - |instance_state| is backed by static storage, so the pointer is // always valid, even after the data source instance is destroyed. // - In the case of a race-on-destruction, we'll still see the latest // backend_id and buffer_id and in the worst case keep trying writing // into the tracing shared memory buffer after stopped. But this isn't // really any worse than the case of the stop IPC being delayed by the // kernel scheduler. The tracing service is robust against data commit // attemps made after tracing is stopped. // There is a theoretical race that would case the wrong behavior w.r.t // writing data in the wrong buffer, but it's so rare that we ignore it: // if the data source is stopped and started kMaxDataSourceInstances // times (so that the same id is recycled) while we are in this function, // we might end up reusing the old data source's backend_id and buffer_id // for the new one, because we don't see the generation change past this // point. But stopping and starting tracing (even once) takes so much // handshaking to make this extremely unrealistic. auto& tls_inst = tls_state_->per_instance[i]; if (PERFETTO_UNLIKELY(!tls_inst.trace_writer)) { // Here we need an acquire barrier, which matches the release-store made // by TracingMuxerImpl::SetupDataSource(), to ensure that the backend_id // and buffer_id are consistent. instances = Traits::GetActiveInstances(trace_point_data) ->load(std::memory_order_acquire); instance_state = static_state_.TryGetCached(instances, i); if (!instance_state || !instance_state->trace_lambda_enabled) continue; tls_inst.backend_id = instance_state->backend_id; tls_inst.backend_connection_id = instance_state->backend_connection_id; tls_inst.buffer_id = instance_state->buffer_id; tls_inst.data_source_instance_id = instance_state->data_source_instance_id; tls_inst.is_intercepted = instance_state->interceptor_id != 0; tls_inst.trace_writer = tracing_impl->CreateTraceWriter( &static_state_, i, instance_state, DataSourceType::kBufferExhaustedPolicy); CreateIncrementalState(&tls_inst); // Even in the case of out-of-IDs, SharedMemoryArbiterImpl returns a // NullTraceWriter. The returned pointer should never be null. assert(tls_inst.trace_writer); } tracing_fn(TraceContext(&tls_inst, i)); } } // Registers the data source on all tracing backends, including ones that // connect after the registration. Doing so enables the data source to receive // Setup/Start/Stop notifications and makes the Trace() method work when // tracing is enabled and the data source is selected. // This must be called after Tracing::Initialize(). // Can return false to signal failure if attemping to register more than // kMaxDataSources (32) data sources types or if tracing hasn't been // initialized. // The optional |constructor_args| will be passed to the data source when it // is constructed. template static bool Register(const DataSourceDescriptor& descriptor, const Args&... constructor_args) { // Silences -Wunused-variable warning in case the trace method is not used // by the translation unit that declares the data source. (void)static_state_; (void)tls_state_; auto factory = [constructor_args...]() { return std::unique_ptr( new DataSourceType(constructor_args...)); }; auto* tracing_impl = internal::TracingMuxer::Get(); return tracing_impl->RegisterDataSource(descriptor, factory, &static_state_); } private: // Traits for customizing the behavior of a specific trace point. struct DefaultTracePointTraits { // By default, every call to DataSource::Trace() will record trace events // for every active instance of that data source. A single trace point can, // however, use a custom set of enable flags for more fine grained control // of when that trace point is active. // // DANGER: when doing this, the data source must use the appropriate memory // fences when changing the state of the bitmap. // // |TraceWithInstances| may be optionally given an additional parameter for // looking up the enable flags. That parameter is passed as |TracePointData| // to |GetActiveInstances|. This is, for example, used by TrackEvent to // implement per-category enabled states. struct TracePointData {}; static constexpr std::atomic* GetActiveInstances(TracePointData) { return &static_state_.valid_instances; } }; // Create the user provided incremental state in the given thread-local // storage. Note: The second parameter here is used to specialize the case // where there is no incremental state type. template static void CreateIncrementalStateImpl( internal::DataSourceInstanceThreadLocalState* tls_inst, const T*) { PERFETTO_DCHECK(!tls_inst->incremental_state); tls_inst->incremental_state_generation = static_state_.incremental_state_generation.load( std::memory_order_relaxed); tls_inst->incremental_state = internal::DataSourceInstanceThreadLocalState::IncrementalStatePointer( reinterpret_cast(new T()), [](void* p) { delete reinterpret_cast(p); }); } static void CreateIncrementalStateImpl( internal::DataSourceInstanceThreadLocalState*, const void*) {} static void CreateIncrementalState( internal::DataSourceInstanceThreadLocalState* tls_inst) { CreateIncrementalStateImpl( tls_inst, static_cast(nullptr)); } // Note that the returned object is one per-thread per-data-source-type, NOT // per data-source *instance*. static internal::DataSourceThreadLocalState* GetOrCreateDataSourceTLS( internal::DataSourceStaticState* static_state) { #if PERFETTO_BUILDFLAG(PERFETTO_OS_IOS) PERFETTO_FATAL("Data source TLS not supported on iOS, see b/158814068"); #endif auto* tracing_impl = internal::TracingMuxer::Get(); internal::TracingTLS* root_tls = tracing_impl->GetOrCreateTracingTLS(); internal::DataSourceThreadLocalState* ds_tls = DataSourceTraits::GetDataSourceTLS(static_state, root_tls); // We keep re-initializing as the initialization is idempotent and not worth // the code for extra checks. ds_tls->static_state = static_state; assert(!ds_tls->root_tls || ds_tls->root_tls == root_tls); ds_tls->root_tls = root_tls; return ds_tls; } // Static state. Accessed by the static Trace() method fastpaths. static internal::DataSourceStaticState static_state_; // This TLS object is a cached raw pointer and has deliberately no destructor. // The Platform implementation is supposed to create and manage the lifetime // of the Platform::ThreadLocalObject and take care of destroying it. // This is because non-POD thread_local variables have subtleties (global // destructors) that we need to defer to the embedder. In chromium's platform // implementation, for instance, the tls slot is implemented using // chromium's base::ThreadLocalStorage. static PERFETTO_THREAD_LOCAL internal::DataSourceThreadLocalState* tls_state_; }; // static template internal::DataSourceStaticState DataSource::static_state_; // static template PERFETTO_THREAD_LOCAL internal::DataSourceThreadLocalState* DataSource::tls_state_; } // namespace perfetto // If placed at the end of a macro declaration, eats the semicolon at the end of // the macro invocation (e.g., "MACRO(...);") to avoid warnings about extra // semicolons. #define PERFETTO_INTERNAL_SWALLOW_SEMICOLON() \ extern int perfetto_internal_unused // This macro must be used once for each data source next to the data source's // declaration. #define PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(...) \ template <> \ PERFETTO_COMPONENT_EXPORT perfetto::internal::DataSourceStaticState \ perfetto::DataSource<__VA_ARGS__>::static_state_; \ template <> \ PERFETTO_COMPONENT_EXPORT PERFETTO_THREAD_LOCAL \ perfetto::internal::DataSourceThreadLocalState* \ perfetto::DataSource<__VA_ARGS__>::tls_state_ // MSVC has a bug where explicit template member specialization declarations // can't have thread_local as the storage class specifier. The generated code // seems correct without the specifier, so drop it until the bug gets fixed. // See https://developercommunity2.visualstudio.com/t/Unable-to-specialize- // static-thread_local/1302689. #if PERFETTO_BUILDFLAG(PERFETTO_COMPILER_MSVC) #define PERFETTO_TEMPLATE_THREAD_LOCAL #else #define PERFETTO_TEMPLATE_THREAD_LOCAL PERFETTO_THREAD_LOCAL #endif // This macro must be used once for each data source in one source file to // allocate static storage for the data source's static state. // // Note: if MSVC fails with a C2086 (redefinition) error here, use the // permissive- flag to enable standards-compliant mode. See // https://developercommunity.visualstudio.com/content/problem/319447/ // explicit-specialization-of-static-data-member-inco.html. #define PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(...) \ template <> \ PERFETTO_COMPONENT_EXPORT perfetto::internal::DataSourceStaticState \ perfetto::DataSource<__VA_ARGS__>::static_state_{}; \ template <> \ PERFETTO_COMPONENT_EXPORT PERFETTO_TEMPLATE_THREAD_LOCAL \ perfetto::internal::DataSourceThreadLocalState* \ perfetto::DataSource<__VA_ARGS__>::tls_state_ = nullptr #endif // INCLUDE_PERFETTO_TRACING_DATA_SOURCE_H_ // gen_amalgamated begin header: include/perfetto/tracing/tracing.h // gen_amalgamated begin header: include/perfetto/tracing/backend_type.h /* * Copyright (C) 2021 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_TRACING_BACKEND_TYPE_H_ #define INCLUDE_PERFETTO_TRACING_BACKEND_TYPE_H_ #include namespace perfetto { enum BackendType : uint32_t { kUnspecifiedBackend = 0, // Connects to a previously-initialized perfetto tracing backend for // in-process. If the in-process backend has not been previously initialized // it will do so and create the tracing service on a dedicated thread. kInProcessBackend = 1 << 0, // Connects to the system tracing service (e.g. on Linux/Android/Mac uses a // named UNIX socket). kSystemBackend = 1 << 1, // Used to provide a custom IPC transport to connect to the service. // TracingInitArgs::custom_backend must be non-null and point to an // indefinitely lived instance. kCustomBackend = 1 << 2, }; } // namespace perfetto #endif // INCLUDE_PERFETTO_TRACING_BACKEND_TYPE_H_ // gen_amalgamated begin header: include/perfetto/tracing/internal/in_process_tracing_backend.h // gen_amalgamated begin header: include/perfetto/tracing/tracing_backend.h /* * Copyright (C) 2019 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_TRACING_TRACING_BACKEND_H_ #define INCLUDE_PERFETTO_TRACING_TRACING_BACKEND_H_ #include #include // gen_amalgamated expanded: #include "perfetto/base/export.h" // The embedder can (but doesn't have to) extend the TracingBackend class and // pass as an argument to Tracing::Initialize(kCustomBackend) to override the // way to reach the service. This is for peculiar cases where the embedder has // a multi-process architecture and wants to override the IPC transport. The // real use-case for this at the time of writing is chromium (+ Mojo IPC). // Extending this class requires depending on the full set of perfetto headers // (not just /public/). Contact the team before doing so as the non-public // headers are not guaranteed to be API stable. namespace perfetto { namespace base { class TaskRunner; } // These classes are declared in headers outside of /public/. class Consumer; class ConsumerEndpoint; class Producer; class ProducerEndpoint; class PERFETTO_EXPORT TracingBackend { public: virtual ~TracingBackend(); // Connects a Producer instance and obtains a ProducerEndpoint, which is // essentially a 1:1 channel between one Producer and the Service. // To disconnect just destroy the returned endpoint object. It is safe to // destroy the Producer once Producer::OnDisconnect() has been invoked. struct ConnectProducerArgs { std::string producer_name; // The Producer object that will receive calls like Start/StopDataSource(). // The caller has to guarantee that this object is valid as long as the // returned ProducerEndpoint is alive. Producer* producer = nullptr; // The task runner where the Producer methods will be called onto. // The caller has to guarantee that the passed TaskRunner is valid as long // as the returned ProducerEndpoint is alive. ::perfetto::base::TaskRunner* task_runner = nullptr; // These get propagated from TracingInitArgs and are optionally provided by // the client when calling Tracing::Initialize(). uint32_t shmem_size_hint_bytes = 0; uint32_t shmem_page_size_hint_bytes = 0; }; virtual std::unique_ptr ConnectProducer( const ConnectProducerArgs&) = 0; // As above, for the Consumer-side. struct ConnectConsumerArgs { // The Consumer object that will receive calls like OnTracingDisabled(), // OnTraceData(). Consumer* consumer{}; // The task runner where the Consumer methods will be called onto. ::perfetto::base::TaskRunner* task_runner{}; }; virtual std::unique_ptr ConnectConsumer( const ConnectConsumerArgs&) = 0; }; } // namespace perfetto #endif // INCLUDE_PERFETTO_TRACING_TRACING_BACKEND_H_ /* * Copyright (C) 2019 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_IN_PROCESS_TRACING_BACKEND_H_ #define INCLUDE_PERFETTO_TRACING_INTERNAL_IN_PROCESS_TRACING_BACKEND_H_ // gen_amalgamated expanded: #include "perfetto/base/export.h" // gen_amalgamated expanded: #include "perfetto/tracing/tracing_backend.h" namespace perfetto { namespace base { class TaskRunner; } class Producer; class TracingService; namespace internal { // A built-in implementation of TracingBackend that creates a tracing service // instance in-process. Instantiated when the embedder calls // Tracing::Initialize(kInProcessBackend). Solves most in-app-only tracing // use-cases. class PERFETTO_EXPORT InProcessTracingBackend : public TracingBackend { public: static TracingBackend* GetInstance(); // TracingBackend implementation. std::unique_ptr ConnectProducer( const ConnectProducerArgs&) override; std::unique_ptr ConnectConsumer( const ConnectConsumerArgs&) override; private: InProcessTracingBackend(); TracingService* GetOrCreateService(base::TaskRunner*); std::unique_ptr service_; }; } // namespace internal } // namespace perfetto #endif // INCLUDE_PERFETTO_TRACING_INTERNAL_IN_PROCESS_TRACING_BACKEND_H_ // gen_amalgamated begin header: include/perfetto/tracing/internal/system_tracing_backend.h /* * Copyright (C) 2019 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_SYSTEM_TRACING_BACKEND_H_ #define INCLUDE_PERFETTO_TRACING_INTERNAL_SYSTEM_TRACING_BACKEND_H_ // gen_amalgamated expanded: #include "perfetto/base/export.h" // gen_amalgamated expanded: #include "perfetto/tracing/tracing_backend.h" namespace perfetto { namespace base { class TaskRunner; } class Producer; // A built-in implementation of TracingBackend that connects to the system // tracing daemon (traced) via a UNIX socket using the perfetto built-in // proto-based IPC mechanism. Instantiated when the embedder calls // Tracing::Initialize(kSystemBackend). It allows to get app-traces fused // together with system traces, useful to correlate on the timeline system // events (e.g. scheduling slices from the kernel) with in-app events. namespace internal { class PERFETTO_EXPORT SystemTracingBackend : public TracingBackend { public: static TracingBackend* GetInstance(); // TracingBackend implementation. std::unique_ptr ConnectProducer( const ConnectProducerArgs&) override; std::unique_ptr ConnectConsumer( const ConnectConsumerArgs&) override; private: SystemTracingBackend(); }; } // namespace internal } // namespace perfetto #endif // INCLUDE_PERFETTO_TRACING_INTERNAL_SYSTEM_TRACING_BACKEND_H_ // gen_amalgamated begin header: include/perfetto/tracing/tracing_policy.h /* * Copyright (C) 2021 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_TRACING_TRACING_POLICY_H_ #define INCLUDE_PERFETTO_TRACING_TRACING_POLICY_H_ #include // gen_amalgamated expanded: #include "perfetto/base/export.h" // gen_amalgamated expanded: #include "perfetto/tracing/backend_type.h" namespace perfetto { // Applies policy decisions, such as allowing or denying connections, when // certain tracing SDK events occur. All methods are called on an internal // perfetto thread. class PERFETTO_EXPORT TracingPolicy { public: virtual ~TracingPolicy(); // Called when the current process attempts to connect a new consumer to the // backend of |backend_type| to check if the connection should be allowed. Its // implementation should execute |result_callback| with the result of the // check (synchronuosly or asynchronously on any thread). If the result is // false, the consumer connection is aborted. Chrome uses this to restrict // creating (system) tracing sessions based on an enterprise policy. struct ShouldAllowConsumerSessionArgs { BackendType backend_type; std::function result_callback; }; virtual void ShouldAllowConsumerSession( const ShouldAllowConsumerSessionArgs&) = 0; }; } // namespace perfetto #endif // INCLUDE_PERFETTO_TRACING_TRACING_POLICY_H_ /* * Copyright (C) 2019 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_TRACING_TRACING_H_ #define INCLUDE_PERFETTO_TRACING_TRACING_H_ #include #include #include #include #include #include // gen_amalgamated expanded: #include "perfetto/base/compiler.h" // gen_amalgamated expanded: #include "perfetto/base/export.h" // gen_amalgamated expanded: #include "perfetto/base/logging.h" // gen_amalgamated expanded: #include "perfetto/tracing/backend_type.h" // gen_amalgamated expanded: #include "perfetto/tracing/core/forward_decls.h" // gen_amalgamated expanded: #include "perfetto/tracing/internal/in_process_tracing_backend.h" // gen_amalgamated expanded: #include "perfetto/tracing/internal/system_tracing_backend.h" // gen_amalgamated expanded: #include "perfetto/tracing/tracing_policy.h" namespace perfetto { namespace internal { class TracingMuxerImpl; } class TracingBackend; class Platform; class TracingSession; // Declared below. struct TracingError { enum ErrorCode : uint32_t { // Peer disconnection. kDisconnected = 1, // The Start() method failed. This is typically because errors in the passed // TraceConfig. More details are available in |message|. kTracingFailed = 2, }; ErrorCode code; std::string message; TracingError(ErrorCode cd, std::string msg) : code(cd), message(std::move(msg)) { PERFETTO_CHECK(!message.empty()); } }; using LogLev = ::perfetto::base::LogLev; using LogMessageCallbackArgs = ::perfetto::base::LogMessageCallbackArgs; using LogMessageCallback = ::perfetto::base::LogMessageCallback; struct TracingInitArgs { uint32_t backends = 0; // One or more BackendTypes. TracingBackend* custom_backend = nullptr; // [Optional]. // [Optional] Platform implementation. It allows the embedder to take control // of platform-specific bits like thread creation and TLS slot handling. If // not set it will use Platform::GetDefaultPlatform(). Platform* platform = nullptr; // [Optional] Tune the size of the shared memory buffer between the current // process and the service backend(s). This is a trade-off between memory // footprint and the ability to sustain bursts of trace writes (see comments // in shared_memory_abi.h). // If set, the value must be a multiple of 4KB. The value can be ignored if // larger than kMaxShmSize (32MB) or not a multiple of 4KB. uint32_t shmem_size_hint_kb = 0; // [Optional] Specifies the preferred size of each page in the shmem buffer. // This is a trade-off between IPC overhead and fragmentation/efficiency of // the shmem buffer in presence of multiple writer threads. // Must be one of [4, 8, 16, 32]. uint32_t shmem_page_size_hint_kb = 0; // [Optional] The length of the period during which shared-memory-buffer // chunks that have been filled with data are accumulated (batched) on the // producer side, before the service is notified of them over an out-of-band // IPC call. If, while this period lasts, the shared memory buffer gets too // full, the IPC call will be sent immediately. The value of this parameter is // a trade-off between IPC traffic overhead and the ability to sustain bursts // of trace writes. The higher the value, the more chunks will be batched and // the less buffer space will be available to hide the latency of the service, // and vice versa. For more details, see the SetBatchCommitsDuration method in // shared_memory_arbiter.h. // // Note: With the default value of 0ms, batching still happens but with a zero // delay, i.e. commits will be sent to the service at the next opportunity. uint32_t shmem_batch_commits_duration_ms = 0; // [Optional] If set, the policy object is notified when certain SDK events // occur and may apply policy decisions, such as denying connections. The // embedder is responsible for ensuring the object remains alive for the // lifetime of the process. TracingPolicy* tracing_policy = nullptr; // [Optional] If set, log messages generated by perfetto are passed to this // callback instead of being logged directly. LogMessageCallback log_message_callback = nullptr; protected: friend class Tracing; friend class internal::TracingMuxerImpl; // Used only by the DCHECK in tracing.cc, to check that the config is the // same in case of re-initialization. bool operator==(const TracingInitArgs& other) const { return std::tie(backends, custom_backend, platform, shmem_size_hint_kb, shmem_page_size_hint_kb, in_process_backend_factory_, system_backend_factory_, dcheck_is_on_) == std::tie(other.backends, other.custom_backend, other.platform, other.shmem_size_hint_kb, other.shmem_page_size_hint_kb, other.in_process_backend_factory_, other.system_backend_factory_, other.dcheck_is_on_); } using BackendFactoryFunction = TracingBackend* (*)(); BackendFactoryFunction in_process_backend_factory_ = nullptr; BackendFactoryFunction system_backend_factory_ = nullptr; bool dcheck_is_on_ = PERFETTO_DCHECK_IS_ON(); }; // The entry-point for using perfetto. class PERFETTO_EXPORT Tracing { public: // Initializes Perfetto with the given backends in the calling process and/or // with a user-provided backend. No-op if called more than once. static inline void Initialize(const TracingInitArgs& args) PERFETTO_ALWAYS_INLINE { TracingInitArgs args_copy(args); // This code is inlined to allow dead-code elimination for unused backends. // This saves ~200 KB when not using the in-process backend (b/148198993). // The logic behind it is the following: // Nothing other than the code below references the two GetInstance() // methods. From a linker-graph viewpoint, those GetInstance() pull in many // other pieces of the codebase (e.g. InProcessTracingBackend pulls the // whole TracingServiceImpl, SystemTracingBackend pulls the whole //ipc // layer). Due to the inline, the compiler can see through the code and // realize that some branches are always not taken. When that happens, no // reference to the backends' GetInstance() is emitted and that allows the // linker GC to get rid of the entire set of dependencies. if (args.backends & kInProcessBackend) { args_copy.in_process_backend_factory_ = &internal::InProcessTracingBackend::GetInstance; } if (args.backends & kSystemBackend) { args_copy.system_backend_factory_ = &internal::SystemTracingBackend::GetInstance; } InitializeInternal(args_copy); } // Checks if tracing has been initialized by calling |Initialize|. static bool IsInitialized(); // Start a new tracing session using the given tracing backend. Use // |kUnspecifiedBackend| to select an available backend automatically. // For the moment this can be used only when initializing tracing in // kInProcess mode. For the system mode use the 'bin/perfetto' cmdline client. static std::unique_ptr NewTrace( BackendType = kUnspecifiedBackend); private: static void InitializeInternal(const TracingInitArgs&); Tracing() = delete; }; class PERFETTO_EXPORT TracingSession { public: virtual ~TracingSession(); // Configure the session passing the trace config. // If a writable file handle is given through |fd|, the trace will // automatically written to that file. Otherwise you should call ReadTrace() // to retrieve the trace data. This call does not take ownership of |fd|. // TODO(primiano): add an error callback. virtual void Setup(const TraceConfig&, int fd = -1) = 0; // Enable tracing asynchronously. Use SetOnStartCallback() to get a // notification when the session has fully started. virtual void Start() = 0; // Enable tracing and block until tracing has started. Note that if data // sources are registered after this call was initiated, the call may return // before the additional data sources have started. Also, if other producers // (e.g., with system-wide tracing) have registered data sources without start // notification support, this call may return before those data sources have // started. virtual void StartBlocking() = 0; // This callback will be invoked when all data sources have acknowledged that // tracing has started. This callback will be invoked on an internal perfetto // thread. virtual void SetOnStartCallback(std::function) = 0; // This callback can be used to get a notification when some error occured // (e.g., peer disconnection). Error type will be passed as an argument. This // callback will be invoked on an internal perfetto thread. virtual void SetOnErrorCallback(std::function) = 0; // Issues a flush request, asking all data sources to ack the request, within // the specified timeout. A "flush" is a fence to ensure visibility of data in // the async tracing pipeline. It guarantees that all data written before the // Flush() call will be visible in the trace buffer and hence by the // ReadTrace() / ReadTraceBlocking() methods. // Args: // callback: will be invoked on an internal perfetto thread when all data // sources have acked, or the timeout is reached. The bool argument // will be true if all data sources acked within the timeout, false if // the timeout was hit or some other error occurred (e.g. the tracing // session wasn't started or ended). // timeout_ms: how much time the service will wait for data source acks. If // 0, the global timeout specified in the TraceConfig (flush_timeout_ms) // will be used. If flush_timeout_ms is also unspecified, a default value // of 5s will be used. // Known issues: // Because flushing is still based on service-side scraping, the very last // trace packet for each data source thread will not be visible. Fixing // this requires either propagating the Flush() to the data sources or // changing the order of atomic operations in the service (b/162206162). // Until then, a workaround is to make sure to call // DataSource::Trace([](TraceContext ctx) { ctx.Flush(); }) just before // stopping, on each thread where DataSource::Trace has been previously // called. virtual void Flush(std::function, uint32_t timeout_ms = 0) = 0; // Blocking version of Flush(). Waits until all data sources have acked and // returns the success/failure status. bool FlushBlocking(uint32_t timeout_ms = 0); // Disable tracing asynchronously. // Use SetOnStopCallback() to get a notification when the tracing session is // fully stopped and all data sources have acked. virtual void Stop() = 0; // Disable tracing and block until tracing has stopped. virtual void StopBlocking() = 0; // This callback will be invoked when tracing is disabled. // This can happen either when explicitly calling TracingSession.Stop() or // when the trace reaches its |duration_ms| time limit. // This callback will be invoked on an internal perfetto thread. virtual void SetOnStopCallback(std::function) = 0; // Changes the TraceConfig for an active tracing session. The session must // have been configured and started before. Note that the tracing service // only supports changing a subset of TraceConfig fields, // see ConsumerEndpoint::ChangeTraceConfig(). virtual void ChangeTraceConfig(const TraceConfig&) = 0; // Struct passed as argument to the callback passed to ReadTrace(). // [data, size] is guaranteed to contain 1 or more full trace packets, which // can be decoded using trace.proto. No partial or truncated packets are // exposed. If the trace is empty this returns a zero-sized nullptr with // |has_more| == true to signal EOF. // This callback will be invoked on an internal perfetto thread. struct ReadTraceCallbackArgs { const char* data = nullptr; size_t size = 0; // When false, this will be the last invocation of the callback for this // read cycle. bool has_more = false; }; // Reads back the trace data (raw protobuf-encoded bytes) asynchronously. // Can be called at any point during the trace, typically but not necessarily, // after stopping. If this is called before the end of the trace (i.e. before // Stop() / StopBlocking()), in almost all cases you need to call // Flush() / FlushBlocking() before Read(). This is to guarantee that tracing // data in-flight in the data sources is committed into the tracing buffers // before reading them. // Reading the trace data is a destructive operation w.r.t. contents of the // trace buffer and is not idempotent. // A single ReadTrace() call can yield >1 callback invocations, until // |has_more| is false. using ReadTraceCallback = std::function; virtual void ReadTrace(ReadTraceCallback) = 0; // Synchronous version of ReadTrace(). It blocks the calling thread until all // the trace contents are read. This is slow and inefficient (involves more // copies) and is mainly intended for testing. std::vector ReadTraceBlocking(); // Struct passed as an argument to the callback for GetTraceStats(). Contains // statistics about the tracing session. struct GetTraceStatsCallbackArgs { // Whether or not querying statistics succeeded. bool success = false; // Serialized TraceStats protobuf message. To decode: // // perfetto::protos::gen::TraceStats trace_stats; // trace_stats.ParseFromArray(args.trace_stats_data.data(), // args.trace_stats_data.size()); // std::vector trace_stats_data; }; // Requests a snapshot of statistical data for this tracing session. Only one // query may be active at a time. This callback will be invoked on an internal // perfetto thread. using GetTraceStatsCallback = std::function; virtual void GetTraceStats(GetTraceStatsCallback) = 0; // Synchronous version of GetTraceStats() for convenience. GetTraceStatsCallbackArgs GetTraceStatsBlocking(); // Struct passed as an argument to the callback for QueryServiceState(). // Contains information about registered data sources. struct QueryServiceStateCallbackArgs { // Whether or not getting the service state succeeded. bool success = false; // Serialized TracingServiceState protobuf message. To decode: // // perfetto::protos::gen::TracingServiceState state; // state.ParseFromArray(args.service_state_data.data(), // args.service_state_data.size()); // std::vector service_state_data; }; // Requests a snapshot of the tracing service state for this session. Only one // request per session may be active at a time. This callback will be invoked // on an internal perfetto thread. using QueryServiceStateCallback = std::function; virtual void QueryServiceState(QueryServiceStateCallback) = 0; // Synchronous version of QueryServiceState() for convenience. QueryServiceStateCallbackArgs QueryServiceStateBlocking(); }; } // namespace perfetto #endif // INCLUDE_PERFETTO_TRACING_TRACING_H_ // gen_amalgamated begin header: include/perfetto/tracing/track_event.h // gen_amalgamated begin header: include/perfetto/base/time.h /* * Copyright (C) 2018 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_BASE_TIME_H_ #define INCLUDE_PERFETTO_BASE_TIME_H_ #include #include #include // gen_amalgamated expanded: #include "perfetto/base/build_config.h" // gen_amalgamated expanded: #include "perfetto/base/logging.h" #if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) #include #include #include #include #endif #if PERFETTO_BUILDFLAG(PERFETTO_OS_WASM) #include #endif namespace perfetto { namespace base { using TimeSeconds = std::chrono::seconds; using TimeMillis = std::chrono::milliseconds; using TimeNanos = std::chrono::nanoseconds; inline TimeNanos FromPosixTimespec(const struct timespec& ts) { return TimeNanos(ts.tv_sec * 1000000000LL + ts.tv_nsec); } void SleepMicroseconds(unsigned interval_us); #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) TimeNanos GetWallTimeNs(); TimeNanos GetThreadCPUTimeNs(); // TODO: Clock that counts time during suspend is not implemented on Windows. inline TimeNanos GetBootTimeNs() { return GetWallTimeNs(); } #elif PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) inline TimeNanos GetWallTimeNs() { auto init_time_factor = []() -> uint64_t { mach_timebase_info_data_t timebase_info; mach_timebase_info(&timebase_info); return timebase_info.numer / timebase_info.denom; }; static uint64_t monotonic_timebase_factor = init_time_factor(); return TimeNanos(mach_absolute_time() * monotonic_timebase_factor); } // TODO: Clock that counts time during suspend is not implemented on Mac. inline TimeNanos GetBootTimeNs() { return GetWallTimeNs(); } inline TimeNanos GetThreadCPUTimeNs() { mach_port_t this_thread = mach_thread_self(); mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT; thread_basic_info_data_t info{}; kern_return_t kr = thread_info(this_thread, THREAD_BASIC_INFO, reinterpret_cast(&info), &count); mach_port_deallocate(mach_task_self(), this_thread); if (kr != KERN_SUCCESS) { PERFETTO_DFATAL("Failed to get CPU time."); return TimeNanos(0); } return TimeNanos(info.user_time.seconds * 1000000000LL + info.user_time.microseconds * 1000LL + info.system_time.seconds * 1000000000LL + info.system_time.microseconds * 1000LL); } #elif PERFETTO_BUILDFLAG(PERFETTO_OS_WASM) inline TimeNanos GetWallTimeNs() { return TimeNanos(static_cast(emscripten_get_now()) * 1000000); } inline TimeNanos GetThreadCPUTimeNs() { return TimeNanos(0); } // TODO: Clock that counts time during suspend is not implemented on WASM. inline TimeNanos GetBootTimeNs() { return GetWallTimeNs(); } #elif PERFETTO_BUILDFLAG(PERFETTO_OS_NACL) // Tracing time doesn't need to work on NaCl since its going away shortly. We // just need to compile on it. The only function NaCl could support is // GetWallTimeNs(), but to prevent false hope we leave it unimplemented. inline TimeNanos GetWallTimeNs() { return TimeNanos(0); } inline TimeNanos GetThreadCPUTimeNs() { return TimeNanos(0); } inline TimeNanos GetBootTimeNs() { return TimeNanos(0); } #else // posix constexpr clockid_t kWallTimeClockSource = CLOCK_MONOTONIC; inline TimeNanos GetTimeInternalNs(clockid_t clk_id) { struct timespec ts = {}; PERFETTO_CHECK(clock_gettime(clk_id, &ts) == 0); return FromPosixTimespec(ts); } // Return ns from boot. Conversely to GetWallTimeNs, this clock counts also time // during suspend (when supported). inline TimeNanos GetBootTimeNs() { // Determine if CLOCK_BOOTTIME is available on the first call. static const clockid_t kBootTimeClockSource = [] { struct timespec ts = {}; int res = clock_gettime(CLOCK_BOOTTIME, &ts); return res == 0 ? CLOCK_BOOTTIME : kWallTimeClockSource; }(); return GetTimeInternalNs(kBootTimeClockSource); } inline TimeNanos GetWallTimeNs() { return GetTimeInternalNs(kWallTimeClockSource); } inline TimeNanos GetThreadCPUTimeNs() { return GetTimeInternalNs(CLOCK_THREAD_CPUTIME_ID); } #endif inline TimeSeconds GetBootTimeS() { return std::chrono::duration_cast(GetBootTimeNs()); } inline TimeMillis GetWallTimeMs() { return std::chrono::duration_cast(GetWallTimeNs()); } inline TimeSeconds GetWallTimeS() { return std::chrono::duration_cast(GetWallTimeNs()); } inline struct timespec ToPosixTimespec(TimeMillis time) { struct timespec ts {}; const long time_s = static_cast(time.count() / 1000); ts.tv_sec = time_s; ts.tv_nsec = (static_cast(time.count()) - time_s * 1000L) * 1000000L; return ts; } std::string GetTimeFmt(const std::string& fmt); } // namespace base } // namespace perfetto #endif // INCLUDE_PERFETTO_BASE_TIME_H_ // gen_amalgamated begin header: include/perfetto/tracing/internal/track_event_data_source.h // gen_amalgamated begin header: include/perfetto/base/template_util.h /* * Copyright (C) 2021 The Android Open Source Project * * 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. */ #ifndef INCLUDE_PERFETTO_BASE_TEMPLATE_UTIL_H_ #define INCLUDE_PERFETTO_BASE_TEMPLATE_UTIL_H_ #include #include namespace perfetto { namespace base { // Helper to express preferences in an overload set. If more than one overload // is available for a given set of parameters the overload with the higher // priority will be chosen. template struct priority_tag : priority_tag {}; template <> struct priority_tag<0> {}; // enable_if_t is an implementation of std::enable_if_t from C++14. // // Specification: // https://en.cppreference.com/w/cpp/types/enable_if template using enable_if_t = typename std::enable_if::type; // decay_t is an implementation of std::decay_t from C++14. // // Specification: // https://en.cppreference.com/w/cpp/types/decay template using decay_t = typename std::decay::type; // remove_cvref is an implementation of std::remove_cvref from // C++20. // // Specification: // https://en.cppreference.com/w/cpp/types/remove_cvref template struct remove_cvref { using type = typename std::remove_cv::type>::type>::type; }; template using remove_cvref_t = typename remove_cvref::type; // Check if a given type is a specialization of a given template: // is_specialization::value. template class Template> struct is_specialization : std::false_type {}; template