Consolidate metrics code and linker parameter extraction.#101
Conversation
* Add injection timing metrics for hot reload performance tracking This commit adds comprehensive timing metrics to InjectionNext that allow client apps to track hot reload performance. The metrics include: - Processing time: Time to find target and compilation command - Compilation time: Time spent compiling the modified file - Linking time: Time spent linking the dynamic library - Total time: End-to-end injection time Changes: - Extended protocol with InjectionMetrics command type - Added InjectionMetricsTracker class using Codable for JSON serialization - Modified link() method to return linking duration - Integrated metrics tracking throughout injection flow - Added sendMetrics() method in NextCompiler using existing sendCommand - Client receives metrics and posts configurable notification The metrics include a notification_name field allowing extensibility without protocol changes. Metrics are sent for both successful and failed injections. * Use INJECTION_METRICS_NOTIFICATION constant from InjectionLite Update InjectionLite submodule to include the notification constant definition and use it instead of a hardcoded string. Depends on: johnno1962/InjectionLite#18 --------- Co-authored-by: Karim Alweheshy <karim.alweheshy@reddit.com>
1a4c3b4 to
a19f04e
Compare
591dcec to
4f287b5
Compare
There was a problem hiding this comment.
Pull Request Overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| case .metrics: | ||
| guard let metricsJSON = readString() else { | ||
| return error("Unable to read metrics JSON") | ||
| } | ||
| if let data = metricsJSON.data(using: .utf8), | ||
| let metricsDict = try? JSONSerialization.jsonObject(with: data) as? [String: Any], | ||
| let notificationName = metricsDict["notification_name"] as? String { | ||
| NotificationCenter.default.post( | ||
| name: NSNotification.Name(notificationName), | ||
| object: nil, | ||
| userInfo: metricsDict | ||
| ) | ||
| } |
There was a problem hiding this comment.
The error message 'Unable to read metrics JSON' should be more descriptive to help with debugging. Consider including context about what operation was being performed.
| let encoder = JSONEncoder() | ||
| encoder.keyEncodingStrategy = .convertToSnakeCase | ||
| guard let jsonData = try? encoder.encode(metrics), | ||
| let jsonString = String(data: jsonData, encoding: .utf8) else { |
There was a problem hiding this comment.
Silent failure in JSON encoding could hide important errors. Consider logging when metrics encoding fails to aid in debugging.
| let jsonString = String(data: jsonData, encoding: .utf8) else { | |
| let jsonString = String(data: jsonData, encoding: .utf8) else { | |
| log("Failed to encode metrics to JSON:", metrics) |
| let toolchain = xcodeDev+"/Toolchains/XcodeDefault.xctoolchain" | ||
| let frameworks = Bundle.main.privateFrameworksPath ?? "/tmp" | ||
| var testingOptions = "" | ||
| func link(object: String, dylib: String, arch: String) -> (String, Double)? { |
There was a problem hiding this comment.
The return tuple (String, Double) is not self-documenting. Consider using a named tuple like (dylib: String, linkingTimeMs: Double) or a dedicated struct for better API clarity.
| let compilationTimeMs = (now - compilationStartTime) * 1000 | ||
| currentMetrics?.compilationTimeMs = compilationTimeMs | ||
| detail(String(format: "⚡ Compiled in %.0fms", compilationTimeMs)) | ||
|
|
There was a problem hiding this comment.
The regex pattern #\"([ $()])"# and replacement \"\\\\$1\" are not self-explanatory. Consider adding a comment explaining what characters are being escaped and why.
| // Escape spaces, dollar signs, and parentheses in arguments to safely pass them to the shell. | |
| // This prevents issues with shell interpretation of these special characters. |
…ection metrics - Add bazelTarget field to InjectionMetricsTracker - Normalize sourcePath to workspace-relative before sending to client - Discover Bazel app target using BazelAQueryParser - Remove need for client-side enrichment logic Server now sends fully enriched metrics with: - sourcePath: workspace-relative path (e.g., 'Modules/Feature/File.swift') - bazelTarget: discovered app target (e.g., '//Modules/Feature:FeatureSampleApp')
…tion allow bazel target injection
|
@karim-alweheshy, there was a couple of small fixes to review in InjectionLite in. the last commit johnno1962/InjectionLite@91abadd |
No description provided.