@@ -8,6 +8,7 @@ open FSharp.Control.Reactive
88open FsToolkit.ErrorHandling
99open Spectre.Console
1010
11+ open NBomber.Contracts
1112open NBomber.Extensions .Data
1213open NBomber.Domain
1314open NBomber.Domain .DomainTypes
@@ -28,32 +29,35 @@ let displayStatus (msg: string) (runAction: StatusContext -> Task<'T>) =
2829 status.StartAsync( msg, runAction)
2930
3031let displayClientPoolProgress ( dep : IGlobalDependency , consoleStatus : StatusContext , pool : ClientPool ) =
31- pool.EventStream
32- |> Observable.takeWhile( function
33- | InitFinished -> false
34- | InitFailed -> false
35- | _ -> true
36- )
37- |> Observable.subscribe( function
38- | StartedInit ( poolName, clientCount) ->
39- dep.Logger.Information( " Start init client factory: {0}, client count: {1}" , poolName, clientCount)
40-
41- | StartedDispose poolName ->
42- dep.Logger.Information( " Start disposing client factory: {0}" , poolName)
43-
44- | ClientInitialized ( poolName, number) ->
45- consoleStatus.Status <- $" Initializing client factory: {Console.okColor poolName}, initialized client: {Console.blueColor number}"
46- consoleStatus.Refresh()
47-
48- | ClientDisposed ( poolName, number, error) ->
49- consoleStatus.Status <- $" Disposing client factory: {Console.okColor poolName}, disposed client: {Console.blueColor number}"
50- consoleStatus.Refresh()
51- error |> Option.iter( fun ex -> dep.Logger.Error( ex, " Client exception occurred" ))
52-
53- | InitFinished
54- | InitFailed -> ()
55- )
56- |> ignore
32+
33+ if dep.ApplicationType = ApplicationType.Console then
34+
35+ pool.EventStream
36+ |> Observable.takeWhile( function
37+ | InitFinished -> false
38+ | InitFailed -> false
39+ | _ -> true
40+ )
41+ |> Observable.subscribe( function
42+ | StartedInit ( poolName, clientCount) ->
43+ dep.Logger.Information( " Start init client factory: {0}, client count: {1}" , poolName, clientCount)
44+
45+ | StartedDispose poolName ->
46+ dep.Logger.Information( " Start disposing client factory: {0}" , poolName)
47+
48+ | ClientInitialized ( poolName, number) ->
49+ consoleStatus.Status <- $" Initializing client factory: {Console.okColor poolName}, initialized client: {Console.blueColor number}"
50+ consoleStatus.Refresh()
51+
52+ | ClientDisposed ( poolName, number, error) ->
53+ consoleStatus.Status <- $" Disposing client factory: {Console.okColor poolName}, disposed client: {Console.blueColor number}"
54+ consoleStatus.Refresh()
55+ error |> Option.iter( fun ex -> dep.Logger.Error( ex, " Client exception occurred" ))
56+
57+ | InitFinished
58+ | InitFailed -> ()
59+ )
60+ |> ignore
5761
5862let printContextInfo ( dep : IGlobalDependency ) =
5963 dep.Logger.Verbose( " NBomberConfig: {NBomberConfig}" , $" %A {dep.NBomberConfig}" )
@@ -113,41 +117,47 @@ module LiveStatusTable =
113117 |> ignore
114118 }
115119
116- let display ( cancelToken : CancellationToken ) ( isWarmUp : bool ) ( scnSchedulers : ScenarioScheduler list ) =
117- let stopWatch = Stopwatch()
118- let mutable refreshTableCounter = 0
120+ let display ( appType : ApplicationType )
121+ ( cancelToken : CancellationToken )
122+ ( isWarmUp : bool )
123+ ( scnSchedulers : ScenarioScheduler list ) =
119124
120- let maxDuration =
121- if isWarmUp then scnSchedulers |> List.map( fun x -> x.Scenario) |> Scenario.getMaxWarmUpDuration
122- else scnSchedulers |> List.map( fun x -> x.Scenario) |> Scenario.getMaxDuration
125+ if appType = ApplicationType.Console then
123126
124- let table = buildTable ()
127+ let stopWatch = Stopwatch()
128+ let mutable refreshTableCounter = 0
125129
126- let liveTable = AnsiConsole.Live( table)
127- liveTable.AutoClear <- false
128- liveTable.Overflow <- VerticalOverflow.Ellipsis
129- liveTable.Cropping <- VerticalOverflowCropping.Bottom
130+ let maxDuration =
131+ if isWarmUp then scnSchedulers |> List.map( fun x -> x.Scenario) |> Scenario.getMaxWarmUpDuration
132+ else scnSchedulers |> List.map( fun x -> x.Scenario) |> Scenario.getMaxDuration
130133
131- stopWatch.Start ()
134+ let table = buildTable ()
132135
133- liveTable.StartAsync( fun ctx -> backgroundTask {
134- while not cancelToken.IsCancellationRequested do
135- try
136- let currentTime = stopWatch.Elapsed
137- if currentTime < maxDuration && refreshTableCounter = 0 then
136+ let liveTable = AnsiConsole.Live( table)
137+ liveTable.AutoClear <- false
138+ liveTable.Overflow <- VerticalOverflow.Ellipsis
139+ liveTable.Cropping <- VerticalOverflowCropping.Bottom
138140
139- do ! renderTable table scnSchedulers
141+ stopWatch.Start ()
140142
141- table.Title <- TableTitle( $" duration: ({currentTime:``hh\: mm\: ss``} - {maxDuration:``hh\: mm\: ss``})" )
142- ctx.Refresh()
143- do ! Task.Delay( 1_000 , cancelToken)
143+ liveTable.StartAsync( fun ctx -> backgroundTask {
144+ while not cancelToken.IsCancellationRequested do
145+ try
146+ let currentTime = stopWatch.Elapsed
147+ if currentTime < maxDuration && refreshTableCounter = 0 then
144148
145- refreshTableCounter <- refreshTableCounter + 1
146- if refreshTableCounter = 5 then refreshTableCounter <- 0
147- with
148- | _ -> ()
149+ do ! renderTable table scnSchedulers
149150
150- table.Title <- TableTitle( $" duration: ({maxDuration:``hh\: mm\: ss``} - {maxDuration:``hh\: mm\: ss``})" )
151- ctx.Refresh()
152- })
153- |> ignore
151+ table.Title <- TableTitle( $" duration: ({currentTime:``hh\: mm\: ss``} - {maxDuration:``hh\: mm\: ss``})" )
152+ ctx.Refresh()
153+ do ! Task.Delay( 1_000 , cancelToken)
154+
155+ refreshTableCounter <- refreshTableCounter + 1
156+ if refreshTableCounter = 5 then refreshTableCounter <- 0
157+ with
158+ | _ -> ()
159+
160+ table.Title <- TableTitle( $" duration: ({maxDuration:``hh\: mm\: ss``} - {maxDuration:``hh\: mm\: ss``})" )
161+ ctx.Refresh()
162+ })
163+ |> ignore
0 commit comments