88
99#include " glean/client/swift/JsonServer.h"
1010#include < folly/json.h>
11+ #include " glean/client/swift/Clock.h"
1112
12- JsonServer::JsonServer () : running_(false ), glassAccess_(nullptr ) {}
13+ JsonServer::JsonServer () : running_(false ), glassAccess_(nullptr ) {
14+ // Initialize ScubaLogger and ScubaData
15+ scubaLogger_ = std::make_unique<facebook::glean::swift::ScubaLogger>();
16+ scubaData_ = std::make_unique<facebook::rfe::ScubaData>(" swift_glass_client" );
17+ }
1318
1419void JsonServer::setGlassAccess (std::unique_ptr<IGlassAccess> glassAccess) {
1520 glassAccess_ = std::move (glassAccess);
@@ -33,6 +38,8 @@ void JsonServer::stop() {
3338void JsonServer::processRequest (
3439 const std::string& requestStr,
3540 std::ostream& output) {
41+ facebook::glean::swift::Clock clock;
42+
3643 try {
3744 auto request = folly::parseJson (requestStr);
3845
@@ -45,72 +52,149 @@ void JsonServer::processRequest(
4552 handleUSRToDefinitionRequest (id, value, output);
4653 } else {
4754 // Send error response for unknown method
48- sendErrorResponse (id, -32601 , " Method not found" , output);
55+ auto duration = clock.duration ();
56+ sendErrorResponse (
57+ id,
58+ -32601 ,
59+ " Method not found" ,
60+ output,
61+ method,
62+ value,
63+ determineUSRType (value),
64+ duration);
4965 }
5066 } catch (const std::exception& e) {
51- // Send parse error response
67+ // Send parse error response - no method/usr available due to parsing error
68+ auto duration = clock.duration ();
5269 sendErrorResponse (
5370 folly::dynamic::object,
5471 -32700 ,
5572 " Parse error: " + std::string (e.what ()),
56- output);
73+ output,
74+ std::nullopt ,
75+ std::nullopt ,
76+ std::nullopt ,
77+ duration);
5778 }
5879}
5980
6081void JsonServer::handleUSRToDefinitionRequest (
6182 const folly::dynamic& id,
6283 const std::string& usr,
6384 std::ostream& output) {
85+ // Start timing for scuba logging
86+ facebook::glean::swift::Clock clock;
87+
6488 if (!glassAccess_) {
89+ auto duration = clock.duration ();
6590 sendErrorResponse (
66- id, -32603 , " Internal error: GlassAccess not initialized" , output);
91+ id,
92+ -32603 ,
93+ " Internal error: GlassAccess not initialized" ,
94+ output,
95+ " USRToDefinition" ,
96+ usr,
97+ determineUSRType (usr),
98+ duration);
6799 return ;
68100 }
69101
70- // Call GlassAccess to get definition locations
71- auto locations = glassAccess_->usrToDefinition (usr);
102+ // Determine USR type and method
103+ facebook::glean::swift::USRType usrType = determineUSRType (usr);
104+ std::string method = (usrType == facebook::glean::swift::USRType::SWIFT )
105+ ? " usrToDefinition"
106+ : " clangUSRToDefinition" ;
72107
73- // Create response
74- folly::dynamic response = folly::dynamic::object ;
75- response[ " id " ] = id ;
108+ facebook::glean::swift::Status status =
109+ facebook::glean::swift::Status:: FAILED ;
110+ std::string error ;
76111
77- if (locations.has_value ()) {
78- // Convert protocol::Location objects to JSON
79- folly::dynamic result = folly::dynamic::array;
80- for (const auto & location : locations.value ()) {
81- folly::dynamic locationJson = folly::dynamic::object;
82- locationJson[" uri" ] = location.uri ;
112+ try {
113+ // Call GlassAccess to get definition locations
114+ auto locations = glassAccess_->usrToDefinition (usr);
115+
116+ // Create response
117+ folly::dynamic response = folly::dynamic::object;
118+ response[" id" ] = id;
119+
120+ if (locations.has_value () && !locations->empty ()) {
121+ // Convert protocol::Location objects to JSON
122+ folly::dynamic result = folly::dynamic::array;
123+ for (const auto & location : locations.value ()) {
124+ folly::dynamic locationJson = folly::dynamic::object;
125+ locationJson[" uri" ] = location.uri ;
126+
127+ folly::dynamic range = folly::dynamic::object;
128+ folly::dynamic start = folly::dynamic::object;
129+ start[" line" ] = location.range .start .line ;
130+ start[" character" ] = location.range .start .character ;
131+
132+ folly::dynamic end = folly::dynamic::object;
133+ end[" line" ] = location.range .end .line ;
134+ end[" character" ] = location.range .end .character ;
135+
136+ range[" start" ] = start;
137+ range[" end" ] = end;
138+ locationJson[" range" ] = range;
139+
140+ result.push_back (locationJson);
141+ }
142+ response[" result" ] = result;
143+ status = facebook::glean::swift::Status::SUCCESS ;
144+ } else {
145+ // No definitions found, return empty array
146+ response[" result" ] = folly::dynamic::array;
147+ status = facebook::glean::swift::Status::NOT_FOUND ;
148+ }
83149
84- folly::dynamic range = folly::dynamic::object;
85- folly::dynamic start = folly::dynamic::object;
86- start[" line" ] = location.range .start .line ;
87- start[" character" ] = location.range .start .character ;
150+ // Calculate duration and log the request
151+ auto duration = clock.duration ();
88152
89- folly::dynamic end = folly::dynamic::object;
90- end[" line" ] = location.range .end .line ;
91- end[" character" ] = location.range .end .character ;
153+ // Use folly::toJson(response) to get the result string for logging
154+ std::string resultStr = folly::toJson (response[" result" ]);
92155
93- range[" start" ] = start;
94- range[" end" ] = end;
95- locationJson[" range" ] = range;
156+ // Log the request to Scuba
157+ scubaLogger_->logRequest (
158+ scubaData_.get (),
159+ method,
160+ usr,
161+ usrType,
162+ resultStr,
163+ status,
164+ duration,
165+ error,
166+ std::nullopt );
96167
97- result.push_back (locationJson);
98- }
99- response[" result" ] = result;
100- } else {
101- // No definitions found, return empty array
102- response[" result" ] = folly::dynamic::array;
103- }
168+ // Send response
169+ output << folly::toJson (response) << " \n " ;
104170
105- // Send response
106- output << folly::toJson (response) << " \n " ;
171+ } catch (const std::exception& e) {
172+ error = e.what ();
173+
174+ // Calculate duration and log the failed request
175+ auto duration = clock.duration ();
176+
177+ sendErrorResponse (
178+ id,
179+ -32603 ,
180+ " Internal error: " + error,
181+ output,
182+ method,
183+ usr,
184+ usrType,
185+ duration);
186+ }
107187}
108188
109189void JsonServer::sendErrorResponse (
110190 const folly::dynamic& id,
111191 int code,
112192 const std::string& message,
113- std::ostream& output) {
193+ std::ostream& output,
194+ const std::optional<std::string>& method,
195+ const std::optional<std::string>& usr,
196+ const std::optional<facebook::glean::swift::USRType>& usrType,
197+ int64_t duration) {
114198 folly::dynamic response = folly::dynamic::object;
115199 response[" id" ] = id;
116200
@@ -120,4 +204,29 @@ void JsonServer::sendErrorResponse(
120204 response[" error" ] = error;
121205
122206 output << folly::toJson (response) << " \n " ;
207+
208+ // Log error to Scuba
209+ if (scubaLogger_ && scubaData_) {
210+ scubaLogger_->logRequest (
211+ scubaData_.get (),
212+ method.value_or (" unknown" ),
213+ usr.value_or (" " ),
214+ usrType.value_or (facebook::glean::swift::USRType::UNKNOWN ),
215+ " []" ,
216+ facebook::glean::swift::Status::FAILED ,
217+ duration,
218+ message,
219+ std::nullopt );
220+ }
221+ }
222+
223+ facebook::glean::swift::USRType JsonServer::determineUSRType (
224+ const std::string& usr) {
225+ if (usr.length () >= 2 && usr.substr (0 , 2 ) == " s:" ) {
226+ return facebook::glean::swift::USRType::SWIFT ;
227+ } else if (usr.length () >= 2 && usr.substr (0 , 2 ) == " c:" ) {
228+ return facebook::glean::swift::USRType::CPP ;
229+ } else {
230+ return facebook::glean::swift::USRType::UNKNOWN ;
231+ }
123232}
0 commit comments