/* * ClientLogEvents.h * * This source file is part of the FoundationDB open source project * * Copyright 2013-2018 Apple Inc. and the FoundationDB project authors * * 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 #ifndef FDBCLIENT_CLIENTLOGEVENTS_H #define FDBCLIENT_CLIENTLOGEVENTS_H namespace FdbClientLogEvents { enum class EventType { GET_VERSION_LATENCY = 0, GET_LATENCY = 1, GET_RANGE_LATENCY = 2, COMMIT_LATENCY = 3, ERROR_GET = 4, ERROR_GET_RANGE = 5, ERROR_COMMIT = 6, UNSET }; enum class TransactionPriorityType { PRIORITY_DEFAULT = 0, PRIORITY_BATCH = 1, PRIORITY_IMMEDIATE = 2, UNSET }; struct Event { Event(EventType t, double ts, const Optional>& dc) : type(t), startTs(ts) { if (dc.present()) dcId = dc.get(); } Event() {} template Ar& serialize(Ar& ar) { if (ar.protocolVersion().version() >= (uint64_t)0x0FDB00B063010001LL) { return serializer(ar, type, startTs, dcId); } else { return serializer(ar, type, startTs); } } EventType type{ EventType::UNSET }; double startTs{ 0 }; Key dcId{}; void logEvent(std::string id, int maxFieldLength) const {} }; struct EventGetVersion : public Event { EventGetVersion() {} template Ar& serialize(Ar& ar) { if (!ar.isDeserializing) return serializer(Event::serialize(ar), latency); else return serializer(ar, latency); } double latency; void logEvent(std::string id, int maxFieldLength) const { TraceEvent("TransactionTrace_GetVersion").detail("TransactionID", id).detail("Latency", latency); } }; // Version V2 of EventGetVersion starting at 6.2 struct EventGetVersion_V2 : public Event { EventGetVersion_V2() {} template Ar& serialize(Ar& ar) { if (!ar.isDeserializing) return serializer(Event::serialize(ar), latency, priorityType); else return serializer(ar, latency, priorityType); } double latency; TransactionPriorityType priorityType{ TransactionPriorityType::UNSET }; void logEvent(std::string id, int maxFieldLength) const { TraceEvent("TransactionTrace_GetVersion") .detail("TransactionID", id) .detail("Latency", latency) .detail("PriorityType", priorityType); } }; // Version V3 of EventGetVersion starting at 6.3 struct EventGetVersion_V3 : public Event { EventGetVersion_V3(double ts, const Optional>& dcId, double lat, TransactionPriority priority, Version version) : Event(EventType::GET_VERSION_LATENCY, ts, dcId), latency(lat), readVersion(version) { switch (priority) { // Unfortunately, the enum serialized here disagrees with the enum used elsewhere for the values used by each // priority case TransactionPriority::IMMEDIATE: priorityType = TransactionPriorityType::PRIORITY_IMMEDIATE; break; case TransactionPriority::DEFAULT: priorityType = TransactionPriorityType::PRIORITY_DEFAULT; break; case TransactionPriority::BATCH: priorityType = TransactionPriorityType::PRIORITY_BATCH; break; default: ASSERT(false); } } EventGetVersion_V3() {} template Ar& serialize(Ar& ar) { if (!ar.isDeserializing) return serializer(Event::serialize(ar), latency, priorityType, readVersion); else return serializer(ar, latency, priorityType, readVersion); } double latency; TransactionPriorityType priorityType{ TransactionPriorityType::UNSET }; Version readVersion; void logEvent(std::string id, int maxFieldLength) const { TraceEvent("TransactionTrace_GetVersion") .detail("TransactionID", id) .detail("Latency", latency) .detail("PriorityType", priorityType) .detail("ReadVersion", readVersion); } }; struct EventGet : public Event { EventGet(double ts, const Optional>& dcId, double lat, int size, const KeyRef& in_key) : Event(EventType::GET_LATENCY, ts, dcId), latency(lat), valueSize(size), key(in_key) {} EventGet() {} template Ar& serialize(Ar& ar) { if (!ar.isDeserializing) return serializer(Event::serialize(ar), latency, valueSize, key); else return serializer(ar, latency, valueSize, key); } double latency; int valueSize; Key key; void logEvent(std::string id, int maxFieldLength) const { TraceEvent("TransactionTrace_Get") .setMaxEventLength(-1) .detail("TransactionID", id) .detail("Latency", latency) .detail("ValueSizeBytes", valueSize) .setMaxFieldLength(maxFieldLength) .detail("Key", key); } }; struct EventGetRange : public Event { EventGetRange(double ts, const Optional>& dcId, double lat, int size, const KeyRef& start_key, const KeyRef& end_key) : Event(EventType::GET_RANGE_LATENCY, ts, dcId), latency(lat), rangeSize(size), startKey(start_key), endKey(end_key) {} EventGetRange() {} template Ar& serialize(Ar& ar) { if (!ar.isDeserializing) return serializer(Event::serialize(ar), latency, rangeSize, startKey, endKey); else return serializer(ar, latency, rangeSize, startKey, endKey); } double latency; int rangeSize; Key startKey; Key endKey; void logEvent(std::string id, int maxFieldLength) const { TraceEvent("TransactionTrace_GetRange") .setMaxEventLength(-1) .detail("TransactionID", id) .detail("Latency", latency) .detail("RangeSizeBytes", rangeSize) .setMaxFieldLength(maxFieldLength) .detail("StartKey", startKey) .detail("EndKey", endKey); } }; struct EventCommit : public Event { EventCommit() {} template Ar& serialize(Ar& ar) { if (!ar.isDeserializing) return serializer(Event::serialize(ar), latency, numMutations, commitBytes, req.transaction, req.arena); else return serializer(ar, latency, numMutations, commitBytes, req.transaction, req.arena); } double latency; int numMutations; int commitBytes; CommitTransactionRequest req; // Only CommitTransactionRef and Arena object within CommitTransactionRequest is serialized void logEvent(std::string id, int maxFieldLength) const { for (auto& read_range : req.transaction.read_conflict_ranges) { TraceEvent("TransactionTrace_Commit_ReadConflictRange") .setMaxEventLength(-1) .detail("TransactionID", id) .setMaxFieldLength(maxFieldLength) .detail("Begin", read_range.begin) .detail("End", read_range.end); } for (auto& write_range : req.transaction.write_conflict_ranges) { TraceEvent("TransactionTrace_Commit_WriteConflictRange") .setMaxEventLength(-1) .detail("TransactionID", id) .setMaxFieldLength(maxFieldLength) .detail("Begin", write_range.begin) .detail("End", write_range.end); } for (auto& mutation : req.transaction.mutations) { TraceEvent("TransactionTrace_Commit_Mutation") .setMaxEventLength(-1) .detail("TransactionID", id) .setMaxFieldLength(maxFieldLength) .detail("Mutation", mutation.toString()); } TraceEvent("TransactionTrace_Commit") .detail("TransactionID", id) .detail("Latency", latency) .detail("NumMutations", numMutations) .detail("CommitSizeBytes", commitBytes); } }; // Version V2 of EventGetVersion starting at 6.3 struct EventCommit_V2 : public Event { EventCommit_V2(double ts, const Optional>& dcId, double lat, int mut, int bytes, Version version, const CommitTransactionRequest& commit_req) : Event(EventType::COMMIT_LATENCY, ts, dcId), latency(lat), numMutations(mut), commitBytes(bytes), commitVersion(version), req(commit_req) {} EventCommit_V2() {} template Ar& serialize(Ar& ar) { if (!ar.isDeserializing) return serializer( Event::serialize(ar), latency, numMutations, commitBytes, commitVersion, req.transaction, req.arena); else return serializer(ar, latency, numMutations, commitBytes, commitVersion, req.transaction, req.arena); } double latency; int numMutations; int commitBytes; Version commitVersion; CommitTransactionRequest req; // Only CommitTransactionRef and Arena object within CommitTransactionRequest is serialized void logEvent(std::string id, int maxFieldLength) const { for (auto& read_range : req.transaction.read_conflict_ranges) { TraceEvent("TransactionTrace_Commit_ReadConflictRange") .setMaxEventLength(-1) .detail("TransactionID", id) .setMaxFieldLength(maxFieldLength) .detail("Begin", read_range.begin) .detail("End", read_range.end); } for (auto& write_range : req.transaction.write_conflict_ranges) { TraceEvent("TransactionTrace_Commit_WriteConflictRange") .setMaxEventLength(-1) .detail("TransactionID", id) .setMaxFieldLength(maxFieldLength) .detail("Begin", write_range.begin) .detail("End", write_range.end); } for (auto& mutation : req.transaction.mutations) { TraceEvent("TransactionTrace_Commit_Mutation") .setMaxEventLength(-1) .detail("TransactionID", id) .setMaxFieldLength(maxFieldLength) .detail("Mutation", mutation.toString()); } TraceEvent("TransactionTrace_Commit") .detail("TransactionID", id) .detail("CommitVersion", commitVersion) .detail("Latency", latency) .detail("NumMutations", numMutations) .detail("CommitSizeBytes", commitBytes); } }; struct EventGetError : public Event { EventGetError(double ts, const Optional>& dcId, int err_code, const KeyRef& in_key) : Event(EventType::ERROR_GET, ts, dcId), errCode(err_code), key(in_key) {} EventGetError() {} template Ar& serialize(Ar& ar) { if (!ar.isDeserializing) return serializer(Event::serialize(ar), errCode, key); else return serializer(ar, errCode, key); } int errCode; Key key; void logEvent(std::string id, int maxFieldLength) const { TraceEvent("TransactionTrace_GetError") .setMaxEventLength(-1) .detail("TransactionID", id) .detail("ErrCode", errCode) .setMaxFieldLength(maxFieldLength) .detail("Key", key); } }; struct EventGetRangeError : public Event { EventGetRangeError(double ts, const Optional>& dcId, int err_code, const KeyRef& start_key, const KeyRef& end_key) : Event(EventType::ERROR_GET_RANGE, ts, dcId), errCode(err_code), startKey(start_key), endKey(end_key) {} EventGetRangeError() {} template Ar& serialize(Ar& ar) { if (!ar.isDeserializing) return serializer(Event::serialize(ar), errCode, startKey, endKey); else return serializer(ar, errCode, startKey, endKey); } int errCode; Key startKey; Key endKey; void logEvent(std::string id, int maxFieldLength) const { TraceEvent("TransactionTrace_GetRangeError") .setMaxEventLength(-1) .detail("TransactionID", id) .detail("ErrCode", errCode) .setMaxFieldLength(maxFieldLength) .detail("StartKey", startKey) .detail("EndKey", endKey); } }; struct EventCommitError : public Event { EventCommitError(double ts, const Optional>& dcId, int err_code, const CommitTransactionRequest& commit_req) : Event(EventType::ERROR_COMMIT, ts, dcId), errCode(err_code), req(commit_req) {} EventCommitError() {} template Ar& serialize(Ar& ar) { if (!ar.isDeserializing) return serializer(Event::serialize(ar), errCode, req.transaction, req.arena); else return serializer(ar, errCode, req.transaction, req.arena); } int errCode; CommitTransactionRequest req; // Only CommitTransactionRef and Arena object within CommitTransactionRequest is serialized void logEvent(std::string id, int maxFieldLength) const { for (auto& read_range : req.transaction.read_conflict_ranges) { TraceEvent("TransactionTrace_CommitError_ReadConflictRange") .setMaxEventLength(-1) .detail("TransactionID", id) .setMaxFieldLength(maxFieldLength) .detail("Begin", read_range.begin) .detail("End", read_range.end); } for (auto& write_range : req.transaction.write_conflict_ranges) { TraceEvent("TransactionTrace_CommitError_WriteConflictRange") .setMaxEventLength(-1) .detail("TransactionID", id) .setMaxFieldLength(maxFieldLength) .detail("Begin", write_range.begin) .detail("End", write_range.end); } for (auto& mutation : req.transaction.mutations) { TraceEvent("TransactionTrace_CommitError_Mutation") .setMaxEventLength(-1) .detail("TransactionID", id) .setMaxFieldLength(maxFieldLength) .detail("Mutation", mutation.toString()); } TraceEvent("TransactionTrace_CommitError").detail("TransactionID", id).detail("ErrCode", errCode); } }; } // namespace FdbClientLogEvents #endif