Skip to content

Commit 731bc23

Browse files
committed
Adds settings for OpenTelemetry
1 parent eaa04fb commit 731bc23

5 files changed

Lines changed: 107 additions & 47 deletions

File tree

src/FsAutoComplete/LspHelpers.fs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,10 @@ type InlineValueDto =
600600
{ Enabled: bool option
601601
Prefix: string option }
602602

603+
type NotificationsDto =
604+
{ Trace: bool option
605+
TraceNamespaces: string array option }
606+
603607
type DebugDto =
604608
{ DontCheckRelatedFiles: bool option
605609
CheckFileDebouncerTimeout: int option
@@ -643,6 +647,7 @@ type FSharpConfigDto =
643647
CodeLenses: CodeLensConfigDto option
644648
PipelineHints: InlineValueDto option
645649
InlayHints: InlayHintDto option
650+
Notifications: NotificationsDto option
646651
Debug: DebugDto option }
647652

648653
type FSharpConfigRequest = { FSharp: FSharpConfigDto }
@@ -673,6 +678,23 @@ type InlineValuesConfig =
673678
{ Enabled = Some true
674679
Prefix = Some "//" }
675680

681+
type NotificationsConfig =
682+
{ Trace: bool
683+
TraceNamespaces: string array }
684+
685+
static member Default =
686+
{ Trace = false
687+
TraceNamespaces = [||] }
688+
689+
static member FromDto(dto: NotificationsDto) : NotificationsConfig =
690+
{ Trace = defaultArg dto.Trace NotificationsConfig.Default.Trace
691+
TraceNamespaces = defaultArg dto.TraceNamespaces NotificationsConfig.Default.TraceNamespaces }
692+
693+
694+
member this.AddDto(dto: NotificationsDto) : NotificationsConfig =
695+
{ Trace = defaultArg dto.Trace this.Trace
696+
TraceNamespaces = defaultArg dto.TraceNamespaces this.TraceNamespaces }
697+
676698
type DebugConfig =
677699
{ DontCheckRelatedFiles: bool
678700
CheckFileDebouncerTimeout: int
@@ -722,6 +744,7 @@ type FSharpConfig =
722744
CodeLenses: CodeLensConfig
723745
InlayHints: InlayHintsConfig
724746
InlineValues: InlineValuesConfig
747+
Notifications: NotificationsConfig
725748
Debug: DebugConfig }
726749

727750
static member Default: FSharpConfig =
@@ -761,6 +784,7 @@ type FSharpConfig =
761784
CodeLenses = CodeLensConfig.Default
762785
InlayHints = InlayHintsConfig.Default
763786
InlineValues = InlineValuesConfig.Default
787+
Notifications = NotificationsConfig.Default
764788
Debug = DebugConfig.Default }
765789

766790
static member FromDto(dto: FSharpConfigDto) : FSharpConfig =
@@ -825,7 +849,7 @@ type FSharpConfig =
825849
| Some ivDto ->
826850
{ Enabled = ivDto.Enabled |> Option.defaultValue true |> Some
827851
Prefix = ivDto.Prefix |> Option.defaultValue "//" |> Some }
828-
852+
Notifications = dto.Notifications |> Option.map NotificationsConfig.FromDto |> Option.defaultValue NotificationsConfig.Default
829853
Debug =
830854
match dto.Debug with
831855
| None -> DebugConfig.Default
@@ -908,6 +932,10 @@ type FSharpConfig =
908932
InlineValues =
909933
{ Enabled = defaultArg (dto.PipelineHints |> Option.map (fun n -> n.Enabled)) x.InlineValues.Enabled
910934
Prefix = defaultArg (dto.PipelineHints |> Option.map (fun n -> n.Prefix)) x.InlineValues.Prefix }
935+
Notifications =
936+
dto.Notifications
937+
|> Option.map x.Notifications.AddDto
938+
|> Option.defaultValue NotificationsConfig.Default
911939
Debug =
912940
match dto.Debug with
913941
| None -> DebugConfig.Default

src/FsAutoComplete/LspServers/AdaptiveFSharpLspServer.fs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,15 @@ type AdaptiveFSharpLspServer(workspaceLoader: IWorkspaceLoader, lspClient: FShar
196196
/// in the future
197197
let selectProject projs = projs |> List.tryHead
198198

199+
let mutable traceNotifications : ProgressListener option = None
200+
let replaceTraceNotification shouldTrace traceNamespaces =
201+
traceNotifications
202+
|> Option.iter dispose
203+
if shouldTrace then
204+
traceNotifications <- Some(new ProgressListener(lspClient, traceNamespaces))
205+
else
206+
traceNotifications <- None
207+
199208
let mutableConfigChanges =
200209
let toCompilerToolArgument (path: string) = sprintf "--compilertool:%s" path
201210

@@ -204,6 +213,8 @@ type AdaptiveFSharpLspServer(workspaceLoader: IWorkspaceLoader, lspClient: FShar
204213
and! checker = checker
205214
and! rootPath = rootPath
206215

216+
replaceTraceNotification config.Notifications.Trace config.Notifications.TraceNamespaces
217+
207218
checker.SetFSIAdditionalArguments
208219
[| yield! config.FSICompilerToolLocations |> Array.map toCompilerToolArgument
209220
yield! config.FSIExtraParameters |]
@@ -307,8 +318,6 @@ type AdaptiveFSharpLspServer(workspaceLoader: IWorkspaceLoader, lspClient: FShar
307318

308319
let fileChecked = Event<ParseAndCheckResults * VolatileFile * CancellationToken>()
309320

310-
do disposables.Add <| new ProgressListener(lspClient)
311-
312321
do
313322
disposables.Add
314323
<| fileParsed.Publish.Subscribe(fun (parseResults, proj, ct) ->
@@ -1703,8 +1712,8 @@ type AdaptiveFSharpLspServer(workspaceLoader: IWorkspaceLoader, lspClient: FShar
17031712
percentage = percentage 0 checksToPerform.Length
17041713
)
17051714

1706-
let maxConcurrency = 3
1707-
// Math.Max(1.0, Math.Floor((float System.Environment.ProcessorCount) * 0.75))
1715+
let maxConcurrency =
1716+
Math.Max(1.0, Math.Floor((float System.Environment.ProcessorCount) * 0.75))
17081717
do! Async.Parallel(checksToPerform, int maxConcurrency) |> Async.Ignore<unit array>
17091718

17101719
}
@@ -2467,7 +2476,6 @@ type AdaptiveFSharpLspServer(workspaceLoader: IWorkspaceLoader, lspClient: FShar
24672476
>> Log.addContextDestructured "parms" p
24682477
>> Log.addExn e
24692478
)
2470-
24712479
return! LspResult.internalError (string e)
24722480
}
24732481

src/FsAutoComplete/LspServers/FSharpLspClient.fs

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -149,25 +149,29 @@ open Ionide.ProjInfo.Logging
149149

150150

151151
/// listener for the the events generated from the fsc ActivitySource
152-
type ProgressListener(lspClient: FSharpLspClient) =
153-
154-
let isOneOf list string = list |> List.exists (fun f -> f string)
152+
type ProgressListener(lspClient: FSharpLspClient, traceNamespace : string array) =
155153

154+
let isOneOf list string = list |> Array.exists (fun f -> f string)
156155

156+
let strEquals (other : string) (this : string) = this.Equals(other, StringComparison.InvariantCultureIgnoreCase)
157157
let strContains (substring: string) (str: string) = str.Contains(substring)
158158

159159
let interestingActivities =
160-
[
161-
162-
strContains "BoundModel."
163-
strContains "IncrementalBuild."
164-
strContains "CheckDeclarations."
165-
strContains "ParseAndCheckInputs."
166-
strContains "BackgroundCompiler."
167-
strContains "IncrementalBuildSyntaxTree."
168-
strContains "ParseAndCheckFile."
169-
strContains "ParseAndCheckInputs."
170-
strContains "CheckDeclarations." ]
160+
traceNamespace
161+
|> Array.map strContains
162+
// [
163+
// strEquals "BoundModel.TypeCheck"
164+
// strContains "BackgroundCompiler."
165+
// // strContains "BoundModel."
166+
// // strContains "IncrementalBuild."
167+
// // strContains "CheckDeclarations."
168+
// // strContains "ParseAndCheckInputs."
169+
// // strContains "BackgroundCompiler."
170+
// // strContains "IncrementalBuildSyntaxTree."
171+
// // strContains "ParseAndCheckFile."
172+
// // strContains "ParseAndCheckInputs."
173+
// // strContains "CheckDeclarations."
174+
// ]
171175

172176
let logger = LogProvider.getLoggerByName "Compiler"
173177

@@ -179,11 +183,13 @@ type ProgressListener(lspClient: FSharpLspClient) =
179183
let isStopped (activity: Activity) =
180184
#if NET6_0
181185
false
186+
||
182187
#else
183188
activity.IsStopped
189+
||
184190
#endif
185191
// giving this 1 seconds to report something, otherwise assume it's a dead activity
186-
|| ((DateTime.UtcNow - activity.StartTimeUtc) > TimeSpan.FromSeconds(1.)
192+
((DateTime.UtcNow - activity.StartTimeUtc) > TimeSpan.FromSeconds(5.)
187193
&& activity.Duration = TimeSpan.Zero)
188194

189195
let getTagItemSafe key (a: Activity) = a.GetTagItem key |> Option.ofObj
@@ -200,7 +206,6 @@ type ProgressListener(lspClient: FSharpLspClient) =
200206
>> Option.map IO.Path.GetFileName
201207
>> Option.defaultValue String.Empty
202208

203-
204209
let getUserOpName =
205210
getTagItemSafe Tracing.SemanticConventions.FCS.userOpName
206211
>> Option.map string
@@ -218,9 +223,17 @@ type ProgressListener(lspClient: FSharpLspClient) =
218223
inflightEvents.TryRemove(a.Id) |> ignore
219224
else
220225
// FSC doesn't start their spans with tags so we have to see if it's been added later https://github.com/dotnet/fsharp/issues/14776
221-
let fileName = getFileName a
222-
let userOpName = getUserOpName a
223-
do! p.Report(message = $"{fileName} - {userOpName}")
226+
let message =
227+
String.Join(" - ",
228+
[
229+
getFileName a
230+
getProject a
231+
getUserOpName a
232+
]
233+
)
234+
235+
236+
do! p.Report(message = message)
224237

225238
match! inbox.TryReceive(250) with
226239
| None ->
@@ -233,10 +246,10 @@ type ProgressListener(lspClient: FSharpLspClient) =
233246
let fileName = getFileName activity
234247
let userOpName = getUserOpName activity
235248

236-
logger.debug (
237-
Log.setMessageI
238-
$"Started : {activity.DisplayName:DisplayName} - {userOpName:UserOpName} - {fileName:fileName}"
239-
)
249+
// logger.debug (
250+
// Log.setMessageI
251+
// $"Started : {activity.DisplayName:DisplayName} - {userOpName:UserOpName} - {fileName:fileName}"
252+
// )
240253

241254
if
242255
activity.DisplayName |> isOneOf interestingActivities
@@ -253,10 +266,10 @@ type ProgressListener(lspClient: FSharpLspClient) =
253266
let userOpName = getUserOpName activity
254267
let duration = activity.Duration.ToString()
255268

256-
logger.debug (
257-
Log.setMessageI
258-
$"Finished : {activity.DisplayName:DisplayName} - {userOpName:UserOpName} - {fileName:fileName} - took {duration:duration}"
259-
)
269+
// logger.debug (
270+
// Log.setMessageI
271+
// $"Finished : {activity.DisplayName:DisplayName} - {userOpName:UserOpName} - {fileName:fileName} - took {duration:duration}"
272+
// )
260273

261274
if activity.DisplayName |> isOneOf interestingActivities then
262275
match inflightEvents.TryRemove(activity.Id) with

src/FsAutoComplete/Parser.fs

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ module Parser =
2222

2323
let mutable tracerProvider = Unchecked.defaultof<_>
2424

25+
26+
2527
[<Struct>]
2628
type Pos = { Line: int; Column: int }
2729

@@ -95,6 +97,12 @@ module Parser =
9597
"Enable LSP Server based on FSharp.Data.Adaptive. Should be more stable, but is experimental."
9698
)
9799

100+
let otelTracingOption =
101+
Option<bool>(
102+
"--otel-tracing-enabled",
103+
"Enabled OpenTelemetry exporter. See https://opentelemetry.io/docs/reference/specification/protocol/exporter/ for environment variables to configure for the exporter."
104+
)
105+
98106
let stateLocationOption =
99107
Option<DirectoryInfo>(
100108
"--state-directory",
@@ -115,6 +123,7 @@ module Parser =
115123
rootCommand.AddOption adaptiveLspServerOption
116124
rootCommand.AddOption logLevelOption
117125
rootCommand.AddOption stateLocationOption
126+
rootCommand.AddOption otelTracingOption
118127

119128

120129

@@ -178,20 +187,21 @@ module Parser =
178187

179188
let configureOTel =
180189
Invocation.InvocationMiddleware(fun ctx next ->
181-
let serviceName = FsAutoComplete.Utils.Tracing.serviceName
182-
let version = FsAutoComplete.Utils.Version.info().Version
183-
184-
tracerProvider <-
185-
Sdk
186-
.CreateTracerProviderBuilder()
187-
.AddSource(serviceName, Tracing.fscServiceName)
188-
.SetResourceBuilder(
189-
ResourceBuilder
190-
.CreateDefault()
191-
.AddService(serviceName = serviceName, serviceVersion = version)
192-
)
193-
.AddOtlpExporter()
194-
.Build()
190+
191+
if ctx.ParseResult.HasOption otelTracingOption then
192+
let serviceName = FsAutoComplete.Utils.Tracing.serviceName
193+
let version = FsAutoComplete.Utils.Version.info().Version
194+
tracerProvider <-
195+
Sdk
196+
.CreateTracerProviderBuilder()
197+
.AddSource(serviceName, Tracing.fscServiceName)
198+
.SetResourceBuilder(
199+
ResourceBuilder
200+
.CreateDefault()
201+
.AddService(serviceName = serviceName, serviceVersion = version)
202+
)
203+
.AddOtlpExporter()
204+
.Build()
195205

196206
next.Invoke(ctx))
197207

test/FsAutoComplete.Tests.Lsp/Helpers.fs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ let defaultConfigDto: FSharpConfigDto =
269269
Some
270270
{ Enabled = Some true
271271
Prefix = Some "//" }
272+
Notifications = None
272273
Debug = None }
273274

274275
let clientCaps: ClientCapabilities =

0 commit comments

Comments
 (0)