Skip to content

Commit 4a10d3d

Browse files
authored
Merge pull request #1615 from ahoppen/adjustable-log-linux
Add configuration options to adjust log level and log privacy level on non-Apple platforms
2 parents 134d362 + 1f74b83 commit 4a10d3d

File tree

7 files changed

+96
-40
lines changed

7 files changed

+96
-40
lines changed

CONTRIBUTING.md

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,14 +98,7 @@ Or to stream the logs as they are produced:
9898
log stream --predicate 'subsystem CONTAINS "org.swift.sourcekit-lsp"' --level debug
9999
```
100100
101-
SourceKit-LSP masks data that may contain private information such as source file names and contents by default. To enable logging of this information, run
102-
103-
```sh
104-
sudo log config --subsystem org.swift.sourcekit-lsp --mode private_data:on
105-
```
106-
107-
To enable more verbose logging on non-macOS platforms, launch sourcekit-lsp with the `SOURCEKITLSP_LOG_LEVEL` environment variable set to `debug`.
108-
101+
SourceKit-LSP masks data that may contain private information such as source file names and contents by default. To enable logging of this information, follow the instructions in [Diagnose Bundle.md](Documentation/Diagnose%20Bundle.md).
109102
110103
## Formatting
111104

Documentation/Configuration File.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ The structure of the file is currently not guaranteed to be stable. Options may
3737
- `indexPrefixMap: [string: string]`: Path remappings for remapping index data for local use.
3838
- `maxCoresPercentageToUseForBackgroundIndexing: double`: A hint indicating how many cores background indexing should use at most (value between 0 and 1). Background indexing is not required to honor this setting
3939
- `updateIndexStoreTimeout: int`: Number of seconds to wait for an update index store task to finish before killing it.
40+
- `logging`: Dictionary with the following keys, changing SourceKit-LSP’s logging behavior on non-Apple platforms. On Apple platforms, logging is done through the [system log](Diagnose%20Bundle.md#Enable%20Extended%20Logging). These options can only be set globally and not per workspace.
41+
- `logLevel: "debug"|"info"|"default"|"error"|"fault"`: The level from which one onwards log messages should be written.
42+
- `privacyLevel: "public"|"private"|"sensitive"`: Whether potentially sensitive information should be redacted. Default is `public`, which redacts potentially sensitive information.
4043
- `defaultWorkspaceType: "buildserver"|"compdb"|"swiftpm"`: Overrides workspace type selection logic.
4144
- `generatedFilesPath: string`: Directory in which generated interfaces and macro expansions should be stored.
4245
- `backgroundIndexing: bool`: Explicitly enable or disable background indexing.

Documentation/Diagnose Bundle.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,20 @@ The diagnose bundle contains the following information:
2020

2121
Extended logging of SourceKit-LSP is not enabled by default because it contains information about your source code, directory structure and similar potentially sensitive information. Instead, the logging system redacts that information. If you are comfortable with sharing such information, you can enable extended SourceKit-LSP’s extended logging, which improves the ability of SourceKit-LSP developers to understand and fix issues.
2222

23+
### macOS
24+
2325
To enable extended logging on macOS, install the configuration profile from https://github.com/swiftlang/sourcekit-lsp/blob/main/Documentation/Enable%20Extended%20Logging.mobileconfig as described in https://support.apple.com/guide/mac-help/configuration-profiles-standardize-settings-mh35561/mac#mchlp41bd550. SourceKit-LSP will immediately stop redacting information and include them in the system log.
2426

2527
To disable extended logging again, remove the configuration profile as described in https://support.apple.com/guide/mac-help/configuration-profiles-standardize-settings-mh35561/mac#mchlpa04df41.
28+
29+
### Non-Apple platforms
30+
31+
Create a [configuration file](Configuration%20File.md) with the following contents at `~/.sourcekit-lsp/config.json` with the following contents:
32+
```json
33+
{
34+
"logging": {
35+
"level": "debug",
36+
"privacyLevel": "private"
37+
}
38+
}
39+
```

Documentation/Environment Variables.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ The following environment variables can be used to control some behavior in Sour
1010

1111
## Runtime
1212

13-
- `SOURCEKITLSP_LOG_LEVEL`: When using `NonDarwinLogger`, specify the level at which messages should be logged. Defaults to `default`. Use `debug` to increase to the highest log level.
14-
- `SOURCEKITLSP_LOG_PRIVACY_LEVEL`: When using `NonDarwinLogger`, specifies whether information that might contain personal information (essentially source code) should be logged. Defaults to `private`, which logs this information. Set to `public` to redact this information.
13+
- `SOURCEKITLSP_LOG_LEVEL`: When using `NonDarwinLogger`, specify the level at which messages should be logged. Defaults to `debug` in debug build and `default` in release builds. Primarily used to increase the log level when running tests from a release build in Swift CI. To adjust the logging on user devices, use the [Configuration file](Configuration%20File.md).
14+
- `SOURCEKITLSP_LOG_PRIVACY_LEVEL`: When using `NonDarwinLogger`, specifies whether information that might contain sensitive information (essentially source code) should be logged. Defaults to `private` in debug build and `public` in release builds. Primarily used to log sensitive information when running tests from a release build in Swift CI. To adjust the logging on user devices, use the [Configuration file](Configuration%20File.md).
1515

1616
## Testing
1717
- `SKIP_LONG_TESTS`: Skip tests that typically take more than 1s to execute.

Sources/SKLogging/NonDarwinLogging.swift

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -23,26 +23,36 @@ import Foundation
2323

2424
package enum LogConfig {
2525
/// The globally set log level
26-
fileprivate static let logLevel: NonDarwinLogLevel = {
27-
if let envVar = ProcessInfo.processInfo.environment["SOURCEKITLSP_LOG_LEVEL"],
28-
let logLevel = NonDarwinLogLevel(envVar)
29-
{
30-
return logLevel
31-
}
32-
#if DEBUG
33-
return .debug
34-
#else
35-
return .default
36-
#endif
37-
}()
26+
package static let logLevel = ThreadSafeBox<NonDarwinLogLevel>(
27+
initialValue: {
28+
if let envVar = ProcessInfo.processInfo.environment["SOURCEKITLSP_LOG_LEVEL"],
29+
let logLevel = NonDarwinLogLevel(envVar)
30+
{
31+
return logLevel
32+
}
33+
#if DEBUG
34+
return .debug
35+
#else
36+
return .default
37+
#endif
38+
}()
39+
)
3840

3941
/// The globally set privacy level
40-
fileprivate static let privacyLevel: NonDarwinLogPrivacy = {
41-
guard let envVar = ProcessInfo.processInfo.environment["SOURCEKITLSP_LOG_PRIVACY_LEVEL"] else {
42+
package static let privacyLevel = ThreadSafeBox<NonDarwinLogPrivacy>(
43+
initialValue: {
44+
if let envVar = ProcessInfo.processInfo.environment["SOURCEKITLSP_LOG_PRIVACY_LEVEL"],
45+
let privacyLevel = NonDarwinLogPrivacy(envVar)
46+
{
47+
return privacyLevel
48+
}
49+
#if DEBUG
4250
return .private
43-
}
44-
return NonDarwinLogPrivacy(envVar) ?? .private
45-
}()
51+
#else
52+
return .public
53+
#endif
54+
}()
55+
)
4656
}
4757

4858
/// A type that is API-compatible to `OSLogType` for all uses within
@@ -114,22 +124,13 @@ package enum NonDarwinLogPrivacy: Comparable, Sendable {
114124
case `private`
115125
case sensitive
116126

117-
init?(_ value: String) {
127+
package init?(_ value: String) {
118128
switch value.lowercased() {
119129
case "sensitive": self = .sensitive
120130
case "private": self = .private
121131
case "public": self = .public
122-
default: break
123-
}
124-
125-
switch Int(value) {
126-
case 0: self = .public
127-
case 1: self = .private
128-
case 2: self = .sensitive
129-
default: break
132+
default: return nil
130133
}
131-
132-
return nil
133134
}
134135
}
135136

@@ -314,8 +315,8 @@ package struct NonDarwinLogger: Sendable {
314315
) {
315316
self.subsystem = subsystem
316317
self.category = category
317-
self.logLevel = logLevel ?? LogConfig.logLevel
318-
self.privacyLevel = privacyLevel ?? LogConfig.privacyLevel
318+
self.logLevel = logLevel ?? LogConfig.logLevel.value
319+
self.privacyLevel = privacyLevel ?? LogConfig.privacyLevel.value
319320
self.overrideLogHandler = overrideLogHandler
320321
}
321322

Sources/SKOptions/SourceKitLSPOptions.swift

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,36 @@ public struct SourceKitLSPOptions: Sendable, Codable, CustomLogStringConvertible
216216
}
217217
}
218218

219+
public struct LoggingOptions: Sendable, Codable, CustomLogStringConvertible {
220+
/// The level from which one onwards log messages should be written.
221+
public var level: String?
222+
/// Whether potentially sensitive information should be redacted.
223+
public var privacyLevel: String?
224+
225+
public init(
226+
level: String? = nil,
227+
privacyLevel: String? = nil
228+
) {
229+
self.level = level
230+
self.privacyLevel = privacyLevel
231+
}
232+
233+
static func merging(base: LoggingOptions, override: LoggingOptions?) -> LoggingOptions {
234+
return LoggingOptions(
235+
level: override?.level ?? base.level,
236+
privacyLevel: override?.privacyLevel ?? base.privacyLevel
237+
)
238+
}
239+
240+
public var description: String {
241+
recursiveDescription(of: self)
242+
}
243+
244+
public var redactedDescription: String {
245+
recursiveRedactedDescription(of: self)
246+
}
247+
}
248+
219249
public enum BackgroundPreparationMode: String {
220250
/// Build a target to prepare it
221251
case build
@@ -234,6 +264,7 @@ public struct SourceKitLSPOptions: Sendable, Codable, CustomLogStringConvertible
234264
public var fallbackBuildSystem: FallbackBuildSystemOptions
235265
public var clangdOptions: [String]?
236266
public var index: IndexOptions
267+
public var logging: LoggingOptions
237268

238269
/// Default workspace type (buildserver|compdb|swiftpm). Overrides workspace type selection logic.
239270
public var defaultWorkspaceType: WorkspaceType?
@@ -307,6 +338,7 @@ public struct SourceKitLSPOptions: Sendable, Codable, CustomLogStringConvertible
307338
compilationDatabase: CompilationDatabaseOptions = .init(),
308339
clangdOptions: [String]? = nil,
309340
index: IndexOptions = .init(),
341+
logging: LoggingOptions = .init(),
310342
defaultWorkspaceType: WorkspaceType? = nil,
311343
generatedFilesPath: String? = nil,
312344
backgroundIndexing: Bool? = nil,
@@ -321,6 +353,7 @@ public struct SourceKitLSPOptions: Sendable, Codable, CustomLogStringConvertible
321353
self.compilationDatabase = compilationDatabase
322354
self.clangdOptions = clangdOptions
323355
self.index = index
356+
self.logging = logging
324357
self.generatedFilesPath = generatedFilesPath
325358
self.defaultWorkspaceType = defaultWorkspaceType
326359
self.backgroundIndexing = backgroundIndexing
@@ -374,6 +407,7 @@ public struct SourceKitLSPOptions: Sendable, Codable, CustomLogStringConvertible
374407
),
375408
clangdOptions: override?.clangdOptions ?? base.clangdOptions,
376409
index: IndexOptions.merging(base: base.index, override: override?.index),
410+
logging: LoggingOptions.merging(base: base.logging, override: override?.logging),
377411
defaultWorkspaceType: override?.defaultWorkspaceType ?? base.defaultWorkspaceType,
378412
generatedFilesPath: override?.generatedFilesPath ?? base.generatedFilesPath,
379413
backgroundIndexing: override?.backgroundIndexing ?? base.backgroundIndexing,
@@ -411,6 +445,7 @@ public struct SourceKitLSPOptions: Sendable, Codable, CustomLogStringConvertible
411445
try container.decodeIfPresent(FallbackBuildSystemOptions.self, forKey: CodingKeys.fallbackBuildSystem) ?? .init()
412446
self.clangdOptions = try container.decodeIfPresent([String].self, forKey: CodingKeys.clangdOptions)
413447
self.index = try container.decodeIfPresent(IndexOptions.self, forKey: CodingKeys.index) ?? .init()
448+
self.logging = try container.decodeIfPresent(LoggingOptions.self, forKey: .logging) ?? .init()
414449
self.defaultWorkspaceType = try container.decodeIfPresent(
415450
WorkspaceType.self,
416451
forKey: CodingKeys.defaultWorkspaceType

Sources/sourcekit-lsp/SourceKitLSP.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,16 @@ struct SourceKitLSP: AsyncParsableCommand {
276276
fatalError("failed to redirect stdout -> stderr: \(strerror(errno)!)")
277277
}
278278

279+
let globalConfigurationOptions = globalConfigurationOptions
280+
if let logLevelStr = globalConfigurationOptions.logging.level, let logLevel = NonDarwinLogLevel(logLevelStr) {
281+
LogConfig.logLevel.value = logLevel
282+
}
283+
if let privacyLevelStr = globalConfigurationOptions.logging.privacyLevel,
284+
let privacyLevel = NonDarwinLogPrivacy(privacyLevelStr)
285+
{
286+
LogConfig.privacyLevel.value = privacyLevel
287+
}
288+
279289
let realStdoutHandle = FileHandle(fileDescriptor: realStdout, closeOnDealloc: false)
280290

281291
// Directory should match the directory we are searching for logs in `DiagnoseCommand.addNonDarwinLogs`.

0 commit comments

Comments
 (0)