Skip to content

Emit signposts for request handling #951

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Sources/LSPLogging/Logging.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,17 @@ import os // os_log

public typealias LogLevel = os.OSLogType
public typealias Logger = os.Logger
public typealias Signposter = OSSignposter

extension os.Logger {
public func makeSignposter() -> Signposter {
return OSSignposter(logger: self)
}
}
#else
public typealias LogLevel = NonDarwinLogLevel
public typealias Logger = NonDarwinLogger
public typealias Signposter = NonDarwinSignposter
#endif

/// The logger that is used to log any messages.
Expand Down
31 changes: 31 additions & 0 deletions Sources/LSPLogging/NonDarwinLogging.swift
Original file line number Diff line number Diff line change
Expand Up @@ -330,4 +330,35 @@ public struct NonDarwinLogger {
public static func flush() {
loggingQueue.sync {}
}

public func makeSignposter() -> NonDarwinSignposter {
return NonDarwinSignposter()
}
}

// MARK: - Signposter

public struct NonDarwinSignpostID {}

public struct NonDarwinSignpostIntervalState {}

/// A type that is API-compatible to `OSLogMessage` for all uses within sourcekit-lsp.
///
/// Since non-Darwin platforms don't have signposts, the type just has no-op operations.
public struct NonDarwinSignposter {
public func makeSignpostID() -> NonDarwinSignpostID {
return NonDarwinSignpostID()
}

public func beginInterval(
_ name: StaticString,
id: NonDarwinSignpostID,
_ message: NonDarwinLogMessage
) -> NonDarwinSignpostIntervalState {
return NonDarwinSignpostIntervalState()
}

public func emitEvent(_ name: StaticString, id: NonDarwinSignpostID, _ message: NonDarwinLogMessage = "") {}

public func endInterval(_ name: StaticString, _ state: NonDarwinSignpostIntervalState, _ message: StaticString) {}
}
6 changes: 6 additions & 0 deletions Sources/SourceKitD/SourceKitD.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ extension SourceKitD {
public func send(_ req: SKDRequestDictionary) async throws -> SKDResponseDictionary {
logRequest(req)

let signposter = logger.makeSignposter()
let signpostID = signposter.makeSignpostID()
let signposterState = signposter.beginInterval("sourcekitd-request", id: signpostID, "Start")

let sourcekitdResponse: SKDResponse = try await withCancellableCheckedThrowingContinuation { continuation in
var handle: sourcekitd_request_handle_t? = nil
api.send_request(req.dict, &handle) { _resp in
Expand All @@ -81,9 +85,11 @@ extension SourceKitD {
logResponse(sourcekitdResponse)

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

signposter.endInterval("sourcekitd-request", signposterState, "Done")
return dict
}
}
Expand Down
14 changes: 13 additions & 1 deletion Sources/SourceKitLSP/SourceKitServer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -628,11 +628,17 @@ extension SourceKitServer: MessageHandler {
self.cancelRequest(params)
}

let notificationID = getNextNotificationIDForLogging()

let signposter = Logger(subsystem: subsystem, category: "notification-\(notificationID)").makeSignposter()
let signpostID = signposter.makeSignpostID()
let state = signposter.beginInterval("Notification", id: signpostID, "\(type(of: params))")
messageHandlingQueue.async(metadata: TaskMetadata(params)) {
let notificationID = getNextNotificationIDForLogging()
signposter.emitEvent("Start handling", id: signpostID)

await withLoggingScope("notification-\(notificationID)") {
await self.handleImpl(params, from: clientID)
signposter.endInterval("Notification", state, "Done")
}
}
}
Expand Down Expand Up @@ -676,9 +682,15 @@ extension SourceKitServer: MessageHandler {
from clientID: ObjectIdentifier,
reply: @escaping (LSPResult<R.Response>) -> Void
) {
let signposter = Logger(subsystem: subsystem, category: "request-\(id)").makeSignposter()
let signpostID = signposter.makeSignpostID()
let state = signposter.beginInterval("Request", id: signpostID, "\(R.self)")

let task = messageHandlingQueue.async(metadata: TaskMetadata(params)) {
signposter.emitEvent("Start handling", id: signpostID)
await withLoggingScope("request-\(id)") {
await self.handleImpl(params, id: id, from: clientID, reply: reply)
signposter.endInterval("Request", state, "Done")
}
// We have handled the request and can't cancel it anymore.
// Stop keeping track of it to free the memory.
Expand Down