OdbDesignLib
OdbDesign ODB++ Parsing Library
 
Loading...
Searching...
No Matches
ComponentHeightTracer.cpp
1#include "ComponentHeightTracer.h"
2#include <Logger.h>
3#include <sstream>
4#include <algorithm>
5#include <cstdlib>
6#include "str_utils.h"
7
8namespace Odb::Lib::FileModel::Design
9{
10 ComponentHeightTracer &ComponentHeightTracer::instance()
11 {
12 static ComponentHeightTracer tracer;
13 return tracer;
14 }
15
16 ComponentHeightTracer::ComponentHeightTracer()
17 {
18 // Default: empty trace set. Use addComponentToTrace() or set
19 // ODBDESIGN_TRACE_COMPONENTS env var (comma-separated) to enable.
20 const char* envComponents = std::getenv("ODBDESIGN_TRACE_COMPONENTS");
21 if (envComponents != nullptr && envComponents[0] != '\0')
22 {
23 std::istringstream stream(envComponents);
24 std::string name;
25 while (std::getline(stream, name, ','))
26 {
27 // Trim whitespace
28 Utils::str_trim(name);
29 if (!name.empty())
30 {
31 m_componentsToTrace.insert(name);
32 }
33 }
34 }
35
36 const char* envMaxFailures = std::getenv("ODBDESIGN_TRACE_MAX_FAILURES");
37 if (envMaxFailures != nullptr)
38 {
39 try
40 {
41 m_maxFailuresToTrace = std::stoi(envMaxFailures);
42 // Validate bounds
43 if (m_maxFailuresToTrace <= 0)
44 {
45 logwarn("[ComponentHeightTracer] ODBDESIGN_TRACE_MAX_FAILURES must be positive, using default value 20");
46 m_maxFailuresToTrace = 20;
47 }
48 }
49 catch (...)
50 {
51 logwarn("[ComponentHeightTracer] Failed to parse ODBDESIGN_TRACE_MAX_FAILURES env var, using default value 20");
52 m_maxFailuresToTrace = 20;
53 }
54 }
55 }
56
57 bool ComponentHeightTracer::shouldTrace(const std::string &compName, unsigned int pkgRef) const
58 {
59 // Check if component is in trace list
60 if (m_componentsToTrace.find(compName) != m_componentsToTrace.end())
61 {
62 return true;
63 }
64 // Check if we should trace failures (first N failures)
65 return shouldTraceFailure();
66 }
67
68 bool ComponentHeightTracer::shouldTraceFailure() const
69 {
70 return m_failureCount.load() < m_maxFailuresToTrace;
71 }
72
73 void ComponentHeightTracer::markFailure() const
74 {
75 m_failureCount.fetch_add(1);
76 }
77
78 std::string ComponentHeightTracer::getCompKey(const std::string &compName, unsigned int pkgRef) const
79 {
80 std::stringstream ss;
81 ss << compName << "(Package=" << pkgRef << ")";
82 return ss.str();
83 }
84
85 std::string ComponentHeightTracer::formatLookupTable(const std::map<std::string, std::string> &lookupTable) const
86 {
87 std::stringstream ss;
88 ss << "{";
89 bool first = true;
90 for (const auto &kv : lookupTable)
91 {
92 if (!first)
93 ss << ", ";
94 ss << "\"" << kv.first << "\":\"" << kv.second << "\"";
95 first = false;
96 }
97 ss << "}";
98 return ss.str();
99 }
100
101 std::string ComponentHeightTracer::formatAttributeNames(const std::vector<std::string> &attributeNames) const
102 {
103 std::stringstream ss;
104 ss << "[";
105 for (size_t i = 0; i < attributeNames.size(); ++i)
106 {
107 if (i > 0)
108 ss << ", ";
109 ss << i << ":\"" << attributeNames[i] << "\"";
110 }
111 ss << "]";
112 return ss.str();
113 }
114
115 void ComponentHeightTracer::logParseStart(const std::string &compName, unsigned int pkgRef, const std::string &attrIdString) const
116 {
117 if (!shouldTrace(compName, pkgRef))
118 return;
119
120 std::stringstream ss;
121 ss << "[CompHeightTrace][PARSE_START] Component=" << compName
122 << ", Package=" << pkgRef
123 << ", attrIdString=\"" << attrIdString << "\"";
124 loginfo(ss.str());
125 }
126
127 void ComponentHeightTracer::logParseResult(const std::string &compName, unsigned int pkgRef,
128 const std::map<std::string, std::string> &lookupTable,
129 const std::vector<std::string> &attributeNames) const
130 {
131 if (!shouldTrace(compName, pkgRef))
132 return;
133
134 std::stringstream ss;
135 ss << "[CompHeightTrace][PARSE_RESULT] Component=" << compName
136 << ", Package=" << pkgRef
137 << ", AttributeNames=" << formatAttributeNames(attributeNames)
138 << ", AttributeLookupTable=" << formatLookupTable(lookupTable);
139
140 // Check if .comp_height is at index 0 and if key "0" exists
141 bool hasCompHeightAttr = !attributeNames.empty() && attributeNames[0] == ".comp_height";
142 bool hasKey0 = lookupTable.find("0") != lookupTable.end();
143
144 ss << ", .comp_height@index0=" << (hasCompHeightAttr ? "YES" : "NO")
145 << ", key\"0\"_exists=" << (hasKey0 ? "YES" : "NO");
146
147 if (hasCompHeightAttr && !hasKey0)
148 {
149 ss << " ⚠️ MISSING_KEY_0";
150 markFailure();
151 }
152 else if (hasKey0)
153 {
154 ss << ", height_value=\"" << lookupTable.at("0") << "\"";
155 }
156
157 loginfo(ss.str());
158 }
159
160 void ComponentHeightTracer::logSerialization(const std::string &compName, unsigned int pkgRef,
161 const std::map<std::string, std::string> &lookupTable,
162 const std::vector<std::string> &attributeNames) const
163 {
164 if (!shouldTrace(compName, pkgRef))
165 return;
166
167 std::stringstream ss;
168 ss << "[CompHeightTrace][SERIALIZE] Component=" << compName
169 << ", Package=" << pkgRef
170 << ", AttributeNames=" << formatAttributeNames(attributeNames)
171 << ", AttributeLookupTable=" << formatLookupTable(lookupTable);
172
173 bool hasKey0 = lookupTable.find("0") != lookupTable.end();
174 if (hasKey0)
175 {
176 ss << ", height_value=\"" << lookupTable.at("0") << "\"";
177 }
178 else
179 {
180 ss << ", key\"0\"_missing";
181 }
182
183 loginfo(ss.str());
184 }
185
186 void ComponentHeightTracer::logGrpcResponse(const std::string &compName, unsigned int pkgRef,
187 const std::map<std::string, std::string> &lookupTable,
188 const std::vector<std::string> &attributeNames) const
189 {
190 if (!shouldTrace(compName, pkgRef))
191 return;
192
193 std::stringstream ss;
194 ss << "[CompHeightTrace][GRPC_RESPONSE] Component=" << compName
195 << ", Package=" << pkgRef
196 << ", AttributeNames=" << formatAttributeNames(attributeNames)
197 << ", AttributeLookupTable=" << formatLookupTable(lookupTable);
198
199 bool hasKey0 = lookupTable.find("0") != lookupTable.end();
200 if (hasKey0)
201 {
202 ss << ", height_value=\"" << lookupTable.at("0") << "\"";
203 }
204 else
205 {
206 ss << ", key\"0\"_missing";
207 }
208
209 loginfo(ss.str());
210 }
211
212 void ComponentHeightTracer::logRestResponse(const std::string &compName, unsigned int pkgRef,
213 const std::map<std::string, std::string> &lookupTable,
214 const std::vector<std::string> &attributeNames) const
215 {
216 if (!shouldTrace(compName, pkgRef))
217 return;
218
219 std::stringstream ss;
220 ss << "[CompHeightTrace][REST_RESPONSE] Component=" << compName
221 << ", Package=" << pkgRef
222 << ", AttributeNames=" << formatAttributeNames(attributeNames)
223 << ", AttributeLookupTable=" << formatLookupTable(lookupTable);
224
225 bool hasKey0 = lookupTable.find("0") != lookupTable.end();
226 if (hasKey0)
227 {
228 ss << ", height_value=\"" << lookupTable.at("0") << "\"";
229 }
230 else
231 {
232 ss << ", key\"0\"_missing";
233 }
234
235 loginfo(ss.str());
236 }
237
238 void ComponentHeightTracer::addComponentToTrace(const std::string &compName)
239 {
240 m_componentsToTrace.insert(compName);
241 }
242
243 void ComponentHeightTracer::setMaxFailuresToTrace(int maxFailures)
244 {
245 m_maxFailuresToTrace = maxFailures;
246 }
247}