Skip to content

Commit 1f74b83

Browse files
committed
Add configuration options to adjust log level and log privacy level on non-Apple platforms
Also adjust the log privacy level on non-Apple platforms to `public` and don’t log potentially sensitive information by default. rdar://132525691 Resolves #1591
1 parent 77e66bd commit 1f74b83

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
@@ -36,6 +36,9 @@ The structure of the file is currently not guaranteed to be stable. Options may
3636
- `indexPrefixMap: [string: string]`: Path remappings for remapping index data for local use.
3737
- `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
3838
- `updateIndexStoreTimeout: int`: Number of seconds to wait for an update index store task to finish before killing it.
39+
- `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.
40+
- `logLevel: "debug"|"info"|"default"|"error"|"fault"`: The level from which one onwards log messages should be written.
41+
- `privacyLevel: "public"|"private"|"sensitive"`: Whether potentially sensitive information should be redacted. Default is `public`, which redacts potentially sensitive information.
3942
- `defaultWorkspaceType: "buildserver"|"compdb"|"swiftpm"`: Overrides workspace type selection logic.
4043
- `generatedFilesPath: string`: Directory in which generated interfaces and macro expansions should be stored.
4144
- `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
@@ -210,6 +210,36 @@ public struct SourceKitLSPOptions: Sendable, Codable, CustomLogStringConvertible
210210
}
211211
}
212212

213+
public struct LoggingOptions: Sendable, Codable, CustomLogStringConvertible {
214+
/// The level from which one onwards log messages should be written.
215+
public var level: String?
216+
/// Whether potentially sensitive information should be redacted.
217+
public var privacyLevel: String?
218+
219+
public init(
220+
level: String? = nil,
221+
privacyLevel: String? = nil
222+
) {
223+
self.level = level
224+
self.privacyLevel = privacyLevel
225+
}
226+
227+
static func merging(base: LoggingOptions, override: LoggingOptions?) -> LoggingOptions {
228+
return LoggingOptions(
229+
level: override?.level ?? base.level,
230+
privacyLevel: override?.privacyLevel ?? base.privacyLevel
231+
)
232+
}
233+
234+
public var description: String {
235+
recursiveDescription(of: self)
236+
}
237+
238+
public var redactedDescription: String {
239+
recursiveRedactedDescription(of: self)
240+
}
241+
}
242+
213243
public enum BackgroundPreparationMode: String {
214244
/// Build a target to prepare it
215245
case build
@@ -228,6 +258,7 @@ public struct SourceKitLSPOptions: Sendable, Codable, CustomLogStringConvertible
228258
public var fallbackBuildSystem: FallbackBuildSystemOptions
229259
public var clangdOptions: [String]?
230260
public var index: IndexOptions
261+
public var logging: LoggingOptions
231262

232263
/// Default workspace type (buildserver|compdb|swiftpm). Overrides workspace type selection logic.
233264
public var defaultWorkspaceType: WorkspaceType?
@@ -301,6 +332,7 @@ public struct SourceKitLSPOptions: Sendable, Codable, CustomLogStringConvertible
301332
compilationDatabase: CompilationDatabaseOptions = .init(),
302333
clangdOptions: [String]? = nil,
303334
index: IndexOptions = .init(),
335+
logging: LoggingOptions = .init(),
304336
defaultWorkspaceType: WorkspaceType? = nil,
305337
generatedFilesPath: String? = nil,
306338
backgroundIndexing: Bool? = nil,
@@ -315,6 +347,7 @@ public struct SourceKitLSPOptions: Sendable, Codable, CustomLogStringConvertible
315347
self.compilationDatabase = compilationDatabase
316348
self.clangdOptions = clangdOptions
317349
self.index = index
350+
self.logging = logging
318351
self.generatedFilesPath = generatedFilesPath
319352
self.defaultWorkspaceType = defaultWorkspaceType
320353
self.backgroundIndexing = backgroundIndexing
@@ -368,6 +401,7 @@ public struct SourceKitLSPOptions: Sendable, Codable, CustomLogStringConvertible
368401
),
369402
clangdOptions: override?.clangdOptions ?? base.clangdOptions,
370403
index: IndexOptions.merging(base: base.index, override: override?.index),
404+
logging: LoggingOptions.merging(base: base.logging, override: override?.logging),
371405
defaultWorkspaceType: override?.defaultWorkspaceType ?? base.defaultWorkspaceType,
372406
generatedFilesPath: override?.generatedFilesPath ?? base.generatedFilesPath,
373407
backgroundIndexing: override?.backgroundIndexing ?? base.backgroundIndexing,
@@ -405,6 +439,7 @@ public struct SourceKitLSPOptions: Sendable, Codable, CustomLogStringConvertible
405439
try container.decodeIfPresent(FallbackBuildSystemOptions.self, forKey: CodingKeys.fallbackBuildSystem) ?? .init()
406440
self.clangdOptions = try container.decodeIfPresent([String].self, forKey: CodingKeys.clangdOptions)
407441
self.index = try container.decodeIfPresent(IndexOptions.self, forKey: CodingKeys.index) ?? .init()
442+
self.logging = try container.decodeIfPresent(LoggingOptions.self, forKey: .logging) ?? .init()
408443
self.defaultWorkspaceType = try container.decodeIfPresent(
409444
WorkspaceType.self,
410445
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)