Skip to content

Commit 47e7a13

Browse files
committed
Emit signposts for request handling
This allows you to trace sourcekit-lsp in Instruments to get a feeling for how long requests take to be handled.
1 parent 9cd33a6 commit 47e7a13

File tree

4 files changed

+58
-1
lines changed

4 files changed

+58
-1
lines changed

Sources/LSPLogging/Logging.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,17 @@ import os // os_log
2727

2828
public typealias LogLevel = os.OSLogType
2929
public typealias Logger = os.Logger
30+
public typealias Signposter = OSSignposter
31+
32+
extension os.Logger {
33+
public func makeSignposter() -> Signposter {
34+
return OSSignposter(logger: self)
35+
}
36+
}
3037
#else
3138
public typealias LogLevel = NonDarwinLogLevel
3239
public typealias Logger = NonDarwinLogger
40+
public typealias Signposter = NonDarwinSignposter
3341
#endif
3442

3543
/// The logger that is used to log any messages.

Sources/LSPLogging/NonDarwinLogging.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,4 +330,35 @@ public struct NonDarwinLogger {
330330
public static func flush() {
331331
loggingQueue.sync {}
332332
}
333+
334+
public func makeSignposter() -> NonDarwinSignposter {
335+
return NonDarwinSignposter()
336+
}
337+
}
338+
339+
// MARK: - Signposter
340+
341+
public struct NonDarwinSignpostID {}
342+
343+
public struct NonDarwinSignpostIntervalState {}
344+
345+
/// A type that is API-compatible to `OSLogMessage` for all uses within sourcekit-lsp.
346+
///
347+
/// Since non-Darwin platforms don't have signposts, the type just has no-op operations.
348+
public struct NonDarwinSignposter {
349+
public func makeSignpostID() -> NonDarwinSignpostID {
350+
return NonDarwinSignpostID()
351+
}
352+
353+
public func beginInterval(
354+
_ name: StaticString,
355+
id: NonDarwinSignpostID,
356+
_ message: NonDarwinLogMessage
357+
) -> NonDarwinSignpostIntervalState {
358+
return NonDarwinSignpostIntervalState()
359+
}
360+
361+
public func emitEvent(_ name: StaticString, id: NonDarwinSignpostID, _ message: NonDarwinLogMessage = "") {}
362+
363+
public func endInterval(_ name: StaticString, _ state: NonDarwinSignpostIntervalState, _ message: StaticString) {}
333364
}

Sources/SourceKitD/SourceKitD.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ extension SourceKitD {
6868
public func send(_ req: SKDRequestDictionary) async throws -> SKDResponseDictionary {
6969
logRequest(req)
7070

71+
let signposter = logger.makeSignposter()
72+
let signpostID = signposter.makeSignpostID()
73+
let signposterState = signposter.beginInterval("sourcekitd-request", id: signpostID, "Start")
74+
7175
let sourcekitdResponse: SKDResponse = try await withCancellableCheckedThrowingContinuation { continuation in
7276
var handle: sourcekitd_request_handle_t? = nil
7377
api.send_request(req.dict, &handle) { _resp in
@@ -81,9 +85,11 @@ extension SourceKitD {
8185
logResponse(sourcekitdResponse)
8286

8387
guard let dict = sourcekitdResponse.value else {
88+
signposter.endInterval("sourcekitd-request", signposterState, "Error")
8489
throw sourcekitdResponse.error!
8590
}
8691

92+
signposter.endInterval("sourcekitd-request", signposterState, "Done")
8793
return dict
8894
}
8995
}

Sources/SourceKitLSP/SourceKitServer.swift

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -628,11 +628,17 @@ extension SourceKitServer: MessageHandler {
628628
self.cancelRequest(params)
629629
}
630630

631+
let notificationID = getNextNotificationIDForLogging()
632+
633+
let signposter = Logger(subsystem: subsystem, category: "notification-\(notificationID)").makeSignposter()
634+
let signpostID = signposter.makeSignpostID()
635+
let state = signposter.beginInterval("Notification", id: signpostID, "\(type(of: params))")
631636
messageHandlingQueue.async(metadata: TaskMetadata(params)) {
632-
let notificationID = getNextNotificationIDForLogging()
637+
signposter.emitEvent("Start handling", id: signpostID)
633638

634639
await withLoggingScope("notification-\(notificationID)") {
635640
await self.handleImpl(params, from: clientID)
641+
signposter.endInterval("Notification", state, "Done")
636642
}
637643
}
638644
}
@@ -676,9 +682,15 @@ extension SourceKitServer: MessageHandler {
676682
from clientID: ObjectIdentifier,
677683
reply: @escaping (LSPResult<R.Response>) -> Void
678684
) {
685+
let signposter = Logger(subsystem: subsystem, category: "request-\(id)").makeSignposter()
686+
let signpostID = signposter.makeSignpostID()
687+
let state = signposter.beginInterval("Request", id: signpostID, "\(R.self)")
688+
679689
let task = messageHandlingQueue.async(metadata: TaskMetadata(params)) {
690+
signposter.emitEvent("Start handling", id: signpostID)
680691
await withLoggingScope("request-\(id)") {
681692
await self.handleImpl(params, id: id, from: clientID, reply: reply)
693+
signposter.endInterval("Request", state, "Done")
682694
}
683695
// We have handled the request and can't cancel it anymore.
684696
// Stop keeping track of it to free the memory.

0 commit comments

Comments
 (0)