cpp/logger/Logger.h (67 lines of code) (raw):

/** * Copyright 2004-present, Facebook, Inc. * * 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. */ #pragma once #include <profilo/LogEntry.h> #include <profilo/entries/Entry.h> #include <profilo/entries/EntryType.h> #include <atomic> #include "PacketLogger.h" #define PROFILOEXPORT __attribute__((visibility("default"))) namespace facebook { namespace profilo { using namespace entries; class Logger { public: struct EntryIDCounter { EntryIDCounter(int32_t initialValue) : id_(initialValue) {} EntryIDCounter(EntryIDCounter& copy) = delete; int32_t next() { int32_t value, newValue; do { value = id_.load(); if (value <= 0 || value == std::numeric_limits<int32_t>::max()) { // explicitly handle overflow and skip negative IDs. newValue = 1; } else { newValue = value + 1; } } while (!id_.compare_exchange_weak(value, newValue)); return value; } private: std::atomic<int32_t> id_; }; static constexpr size_t kMaxVariableLengthEntry = 1024; // Start first entry shifted to allow safely adding extra entries to the trace // after completion. static constexpr int32_t kDefaultInitialID = 512; static EntryIDCounter& getGlobalEntryID(); template <class T> int32_t write(T&& entry) { if (entry.id == 0) { entry.id = entryID_.next(); } using U = std::decay_t<T>; auto size = U::calculateSize(entry); char payload[size]; U::pack(entry, payload, size); logger_.write(payload, size); return entry.id; } template <class T> int32_t writeAndGetCursor(T&& entry, TraceBuffer::Cursor& cursor) { if (entry.id == 0) { entry.id = entryID_.next(); } using U = std::decay_t<T>; auto size = U::calculateSize(entry); char payload[size]; U::pack(entry, payload, size); cursor = logger_.writeAndGetCursor(payload, size); return entry.id; } PROFILOEXPORT int32_t writeBytes(EntryType type, int32_t arg1, const uint8_t* arg2, size_t len); // This constructor is for internal framework use. Logger(logger::TraceBufferProvider provider, EntryIDCounter& counter); private: EntryIDCounter& entryID_; logger::PacketLogger logger_; Logger(const Logger& other) = delete; }; } // namespace profilo } // namespace facebook