1 /* 2 * Copyright (c) Facebook, Inc. and its affiliates. 3 * 4 * This source code is licensed under the MIT license found in the 5 * LICENSE file in the root directory of this source tree. 6 * 7 */ 8 9 #pragma once 10 #include <fstream> 11 #include <sstream> 12 13 #include <folly/compression/Compression.h> 14 #include <folly/dynamic.h> 15 #include <folly/logging/AsyncFileWriter.h> 16 #include <quic/codec/Types.h> 17 #include <quic/logging/BaseQLogger.h> 18 #include <quic/logging/QLoggerConstants.h> 19 #include <quic/logging/QLoggerTypes.h> 20 21 namespace quic { 22 23 class FileQLogger : public BaseQLogger { 24 const static uint64_t kCompressionBufferSize = 1024; // 1 KB 25 26 public: 27 inline const static std::string kQlogExtension = ".qlog"; 28 inline const static std::string kCompressedQlogExtension = ".qlog.gz"; 29 30 using QLogger::TransportSummaryArgs; 31 std::vector<std::unique_ptr<QLogEvent>> logs; 32 FileQLogger( 33 VantagePoint vantagePointIn, 34 std::string protocolTypeIn = kHTTP3ProtocolType, 35 std::string path = "", 36 bool prettyJson = true, 37 bool streaming = false, 38 bool compress = false) BaseQLogger(vantagePointIn,std::move (protocolTypeIn))39 : BaseQLogger(vantagePointIn, std::move(protocolTypeIn)), 40 path_(std::move(path)), 41 prettyJson_(prettyJson), 42 streaming_(streaming), 43 compress_{compress} {} 44 ~FileQLogger()45 ~FileQLogger() override { 46 if (streaming_ && dcid.hasValue()) { 47 finishStream(); 48 } 49 } 50 void addPacket(const RegularQuicPacket& regularPacket, uint64_t packetSize) 51 override; 52 void addPacket( 53 const VersionNegotiationPacket& versionPacket, 54 uint64_t packetSize, 55 bool isPacketRecvd) override; 56 void addPacket(const RegularQuicWritePacket& writePacket, uint64_t packetSize) 57 override; 58 void addPacket( 59 const RetryPacket& retryPacket, 60 uint64_t packetSize, 61 bool isPacketRecvd) override; 62 void addConnectionClose( 63 std::string error, 64 std::string reason, 65 bool drainConnection, 66 bool sendCloseImmediately) override; 67 void addTransportSummary(const TransportSummaryArgs& args) override; 68 void addCongestionMetricUpdate( 69 uint64_t bytesInFlight, 70 uint64_t currentCwnd, 71 std::string congestionEvent, 72 std::string state = "", 73 std::string recoveryState = "") override; 74 void addPacingMetricUpdate( 75 uint64_t pacingBurstSizeIn, 76 std::chrono::microseconds pacingIntervalIn) override; 77 void addPacingObservation( 78 std::string actual, 79 std::string expected, 80 std::string conclusion) override; 81 void addBandwidthEstUpdate(uint64_t bytes, std::chrono::microseconds interval) 82 override; 83 void addAppLimitedUpdate() override; 84 void addAppUnlimitedUpdate() override; 85 void addAppIdleUpdate(std::string idleEvent, bool idle) override; 86 void addPacketDrop(size_t packetSize, std::string dropReasonIn) override; 87 void addDatagramReceived(uint64_t dataLen) override; 88 void addLossAlarm( 89 PacketNum largestSent, 90 uint64_t alarmCount, 91 uint64_t outstandingPackets, 92 std::string type) override; 93 void addPacketsLost( 94 PacketNum largestLostPacketNum, 95 uint64_t lostBytes, 96 uint64_t lostPackets) override; 97 void addTransportStateUpdate(std::string update) override; 98 void addPacketBuffered(ProtectionType protectionType, uint64_t packetSize) 99 override; 100 void addMetricUpdate( 101 std::chrono::microseconds latestRtt, 102 std::chrono::microseconds mrtt, 103 std::chrono::microseconds srtt, 104 std::chrono::microseconds ackDelay) override; 105 void addStreamStateUpdate( 106 StreamId id, 107 std::string update, 108 folly::Optional<std::chrono::milliseconds> timeSinceStreamCreation) 109 override; 110 virtual void addConnectionMigrationUpdate(bool intentionalMigration) override; 111 virtual void addPathValidationEvent(bool success) override; 112 void addPriorityUpdate( 113 quic::StreamId streamId, 114 uint8_t urgency, 115 bool incremental) override; 116 117 void outputLogsToFile(const std::string& path, bool prettyJson); 118 folly::dynamic toDynamic() const; 119 folly::dynamic toDynamicBase() const; 120 folly::dynamic generateSummary( 121 size_t numEvents, 122 std::chrono::microseconds startTime, 123 std::chrono::microseconds endTime) const; 124 125 void setDcid(folly::Optional<ConnectionId> connID) override; 126 void setScid(folly::Optional<ConnectionId> connID) override; 127 128 private: 129 void setupStream(); 130 void writeToStream(folly::StringPiece message); 131 void finishStream(); 132 void handleEvent(std::unique_ptr<QLogEvent> event); 133 134 std::unique_ptr<folly::AsyncFileWriter> writer_; 135 std::unique_ptr<folly::io::StreamCodec> compressionCodec_; 136 std::unique_ptr<folly::IOBuf> compressionBuffer_; 137 138 std::string path_; 139 std::string basePadding_ = " "; 140 std::string eventsPadding_ = ""; 141 std::string eventLine_; 142 std::string token_; 143 std::string endLine_; 144 std::stringstream baseJson_; 145 146 bool prettyJson_; 147 bool streaming_; 148 bool compress_; 149 int numEvents_ = 0; 150 std::chrono::microseconds startTime_ = std::chrono::microseconds::zero(); 151 std::chrono::microseconds endTime_; 152 153 size_t pos_; 154 }; 155 } // namespace quic 156