File indexing completed on 2025-01-18 10:01:40
0001
0002
0003
0004
0005 #pragma once
0006
0007 #include <vector>
0008 #include <string>
0009 #include <cassert>
0010 #include <sys/time.h>
0011 #include <chrono>
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 class JCallGraphRecorder {
0033 public:
0034 enum JDataSource {
0035 DATA_NOT_AVAILABLE = 1,
0036 DATA_FROM_CACHE,
0037 DATA_FROM_SOURCE,
0038 DATA_FROM_FACTORY
0039 };
0040
0041 enum JDataOrigin {
0042 ORIGIN_NOT_AVAILABLE = 1,
0043 ORIGIN_FROM_FACTORY,
0044 ORIGIN_FROM_SOURCE
0045 };
0046
0047 struct JCallGraphNode {
0048 std::string caller_name;
0049 std::string caller_tag;
0050 std::string callee_name;
0051 std::string callee_tag;
0052 std::chrono::steady_clock::time_point start_time;
0053 std::chrono::steady_clock::time_point end_time;
0054 JDataSource data_source = DATA_NOT_AVAILABLE;
0055 JCallGraphNode() {}
0056 JCallGraphNode(std::string caller_name, std::string caller_tag, std::string callee_name, std::string callee_tag)
0057 : caller_name(caller_name), caller_tag(caller_tag), callee_name(callee_name), callee_tag(callee_tag) {}
0058 };
0059
0060 struct JCallStackFrame {
0061 std::string factory_name;
0062 std::string factory_tag;
0063 std::chrono::steady_clock::time_point start_time;
0064 };
0065
0066 struct JErrorCallStack {
0067 std::string factory_name;
0068 std::string tag;
0069 const char* filename;
0070 int line = 0;
0071 };
0072
0073 private:
0074 bool m_enabled = false;
0075 std::vector<JCallStackFrame> m_call_stack;
0076 std::vector<JErrorCallStack> m_error_call_stack;
0077 std::vector<JCallGraphNode> m_call_graph;
0078 JDataOrigin m_insert_dataorigin_type = ORIGIN_FROM_FACTORY;
0079
0080 public:
0081 inline bool IsEnabled() const { return m_enabled; }
0082 inline void SetEnabled(bool recordingEnabled=true){ m_enabled = recordingEnabled; }
0083 inline void StartFactoryCall(const std::string& callee_name, const std::string& callee_tag);
0084 inline JDataOrigin SetInsertDataOrigin(JDataOrigin origin){ auto previous = m_insert_dataorigin_type; m_insert_dataorigin_type = origin; return previous; }
0085 inline JDataOrigin GetInsertDataOrigin(){ return m_insert_dataorigin_type; }
0086 inline void FinishFactoryCall(JDataSource data_source=JDataSource::DATA_FROM_FACTORY);
0087 inline std::vector<JCallGraphNode> GetCallGraph() {return m_call_graph;}
0088 inline void AddToCallGraph(const JCallGraphNode &cs) {if(m_enabled) m_call_graph.push_back(cs);}
0089 inline void AddToErrorCallStack(const JErrorCallStack &cs) {if (m_enabled) m_error_call_stack.push_back(cs);}
0090 inline std::vector<JErrorCallStack> GetErrorCallStack(){return m_error_call_stack;}
0091 void PrintErrorCallStack() const;
0092 void Reset();
0093 std::vector<std::pair<std::string, std::string>> TopologicalSort() const;
0094 };
0095
0096
0097
0098 void JCallGraphRecorder::StartFactoryCall(const std::string& callee_name, const std::string& callee_tag) {
0099
0100
0101
0102
0103
0104
0105
0106 if (!m_enabled) return;
0107 JCallStackFrame frame;
0108 frame.factory_name = callee_name;
0109 frame.factory_tag = callee_tag;
0110 frame.start_time = std::chrono::steady_clock::now();
0111 m_call_stack.push_back(frame);
0112 }
0113
0114
0115 void JCallGraphRecorder::FinishFactoryCall(JCallGraphRecorder::JDataSource data_source) {
0116
0117
0118
0119
0120
0121 if (!m_enabled) return;
0122 assert(!m_call_stack.empty());
0123
0124 JCallStackFrame& callee_frame = m_call_stack.back();
0125
0126 JCallGraphNode node;
0127 node.callee_name = callee_frame.factory_name;
0128 node.callee_tag = callee_frame.factory_tag;
0129 node.start_time = callee_frame.start_time;
0130 node.end_time = std::chrono::steady_clock::now();
0131 node.data_source = data_source;
0132
0133 m_call_stack.pop_back();
0134
0135 if (!m_call_stack.empty()) {
0136 JCallStackFrame& caller_frame = m_call_stack.back();
0137 node.caller_name = caller_frame.factory_name;
0138 node.caller_tag = caller_frame.factory_tag;
0139 m_call_graph.push_back(node);
0140 }
0141 }
0142
0143