Cricket


Tracing

let traceWriter = new InMemoryTraceWriter()
let rnd = new Random()

ActorHost.Start(tracing = TracingConfiguration.Create(enabled = true, writer = traceWriter))


type Message =
    | Request of Guid option * string
    | Response of Guid option * string 

let middleTier responseString = actor {
    body (
        let rec loop() = messageHandler {
            let! msg = Message.receive()
            match msg with
            | Request(Some(id),payload) ->
                 do! Async.Sleep(rnd.Next(500, 3000))
                 do! Message.reply (Response(Some id, responseString + payload))
                 return! loop()
            | _ -> return! loop()
        }
        loop()
    )
}

let bRef = 
    actor { 
        inherits (middleTier "response_B_")
        name "B"
    } |> Actor.spawn

let cRef = 
    actor { 
        inherits (middleTier "response_C_")
        name "C"
    } |> Actor.spawn

let frontEnd = 
    actor {
        name "A"
        body (
            let middleTier = !~["B"; "C"]
            let rec loop state = messageHandler {
                let! msg = Message.receive()
                let! sender = Message.sender()
                match msg with
                | Request(Some(id),payload) ->
                     do! Async.Sleep(rnd.Next(500, 3000))
                     do! Message.post middleTier (Request(Some id, payload))
                     return! loop (Map.add id (sender,[]) state)
                | Response(Some id, payload) ->
                    match state.TryFind(id) with
                    | Some(s,[]) -> return! loop (Map.add id (s,[payload]) state)
                    | Some(s,[h]) -> 
                        do! Message.post s (Response(Some(id), h + "_" + payload))
                        return! loop (Map.remove id state)
                    | _ -> return! loop state
                | _ -> return! loop state
                return! loop state     
            }
           loop Map.empty
        )
    } |> Actor.spawn

let client = 
    actor {
        name "client"
        body (
            let frontend = !~"A"
            let rec loop() = messageHandler {
                let! msg = Message.receive()
                match msg with
                | Request(_,msg) ->
                    do! Async.Sleep(rnd.Next(500, 3000)) 
                    do! Message.post frontend (Request(Some (Guid.NewGuid()), msg))
                    return! loop()
                | Response(_,payload) -> 
                    do! Async.Sleep(rnd.Next(500, 900))
                    printfn "Received response %s" payload
                    return! loop()
            }
            loop()
        )
    } |> Actor.spawn


client <-- Request(None, "Hello")

let rawTraces = traceWriter.GetTraces()

let timeLine() = 
    rawTraces
    |> Seq.groupBy (fun t -> t.SpanId)
    |> Seq.collect (fun (_, ts) -> 
         ts 
         |> Seq.groupBy (fun x -> x.SpanId) 
         |> Seq.choose (fun (_,t) -> 
             let t = t |> Seq.sortBy (fun x -> x.Timestamp) |> Seq.toList
             match t with
             | [h;t] -> Some(t.Actor.Path, t.Sender.Path, (DateTime h.Timestamp), (DateTime t.Timestamp))
             | _ -> failwithf "Unexpected paring %A" t
         )
         |> Seq.toArray
        )
    |> Seq.toList

let data = timeLine()
namespace System
namespace Cricket
namespace Cricket.Diagnostics
val traceWriter : InMemoryTraceWriter

Full name: Diagnostics_tracing.traceWriter
Multiple items
type InMemoryTraceWriter =
  interface ITraceWriter
  new : unit -> InMemoryTraceWriter
  member GetTraces : unit -> TraceEntry []

Full name: Cricket.Diagnostics.InMemoryTraceWriter

--------------------
new : unit -> InMemoryTraceWriter
val rnd : Random

Full name: Diagnostics_tracing.rnd
Multiple items
type Random =
  new : unit -> Random + 1 overload
  member Next : unit -> int + 2 overloads
  member NextBytes : buffer:byte[] -> unit
  member NextDouble : unit -> float

Full name: System.Random

--------------------
Random() : unit
Random(Seed: int) : unit
type ActorHost =
  interface IDisposable
  private new : configuration:ActorHostConfiguration -> ActorHost
  member private Configure : f:(ActorHostConfiguration -> ActorHostConfiguration) -> unit
  member private RegisterActor : ref:ActorRef -> unit
  member private ResolveActor : name:ActorPath -> ActorRef list
  member SubscribeEvents : eventF:('a0 -> unit) -> ActorHost
  member private CancelToken : CancellationToken
  member private EventStream : IEventStream
  member private Name : string
  static member Dispose : unit -> unit
  ...

Full name: Cricket.ActorHost
static member ActorHost.Start : ?name:string * ?loggers:ILogWriter list * ?serializer:'a0 * ?registry:ActorRegistry * ?metrics:MetricsConfiguration * ?tracing:TracingConfiguration * ?cancellationToken:Threading.CancellationToken -> ActorHost
type TracingConfiguration =
  {IsEnabled: bool;
   EnableSystemActorTracing: bool;
   CancellationToken: CancellationToken;
   Writer: ITraceWriter;}
  static member Create : ?enabled:bool * ?systemActorTrace:bool * ?writer:ITraceWriter * ?cancelToken:CancellationToken -> TracingConfiguration

Full name: Cricket.Diagnostics.TracingConfiguration
static member TracingConfiguration.Create : ?enabled:bool * ?systemActorTrace:bool * ?writer:ITraceWriter * ?cancelToken:Threading.CancellationToken -> TracingConfiguration
Multiple items
module Message

from Cricket

--------------------
type Message =
  | Request of Guid option * string
  | Response of Guid option * string

Full name: Diagnostics_tracing.Message

--------------------
type Message<'a> =
  {Id: uint64 option;
   Sender: ActorRef;
   Message: 'a;}

Full name: Cricket.Message<_>
union case Message.Request: Guid option * string -> Message
Multiple items
type Guid =
  struct
    new : b:byte[] -> Guid + 4 overloads
    member CompareTo : value:obj -> int + 1 overload
    member Equals : o:obj -> bool + 1 overload
    member GetHashCode : unit -> int
    member ToByteArray : unit -> byte[]
    member ToString : unit -> string + 2 overloads
    static val Empty : Guid
    static member NewGuid : unit -> Guid
    static member Parse : input:string -> Guid
    static member ParseExact : input:string * format:string -> Guid
    ...
  end

Full name: System.Guid

--------------------
Guid()
Guid(b: byte []) : unit
Guid(g: string) : unit
Guid(a: int, b: int16, c: int16, d: byte []) : unit
Guid(a: uint32, b: uint16, c: uint16, d: byte, e: byte, f: byte, g: byte, h: byte, i: byte, j: byte, k: byte) : unit
Guid(a: int, b: int16, c: int16, d: byte, e: byte, f: byte, g: byte, h: byte, i: byte, j: byte, k: byte) : unit
type 'T option = Option<'T>

Full name: Microsoft.FSharp.Core.option<_>
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string
union case Message.Response: Guid option * string -> Message
val middleTier : responseString:string -> ActorConfiguration<Message>

Full name: Diagnostics_tracing.middleTier
val responseString : string
val actor : ActorConfigurationBuilder

Full name: Cricket.ActorConfiguration.actor
custom operation: body (MessageHandler<ActorCell<'a>,unit>)

Calls ActorConfigurationBuilder.Body
val loop : (unit -> MessageHandler<ActorCell<Message>,'a>)
val messageHandler : Message.MessageHandlerBuilder

Full name: Cricket.ActorConfiguration.messageHandler
val msg : Message
val receive : unit -> MessageHandler<ActorCell<'a>,'a>

Full name: Cricket.Message.receive
union case Option.Some: Value: 'T -> Option<'T>
val id : Guid
val payload : string
Multiple items
type Async
static member AsBeginEnd : computation:('Arg -> Async<'T>) -> ('Arg * AsyncCallback * obj -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit)
static member AwaitEvent : event:IEvent<'Del,'T> * ?cancelAction:(unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate)
static member AwaitIAsyncResult : iar:IAsyncResult * ?millisecondsTimeout:int -> Async<bool>
static member AwaitTask : task:Task<'T> -> Async<'T>
static member AwaitWaitHandle : waitHandle:WaitHandle * ?millisecondsTimeout:int -> Async<bool>
static member CancelDefaultToken : unit -> unit
static member Catch : computation:Async<'T> -> Async<Choice<'T,exn>>
static member FromBeginEnd : beginAction:(AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg:'Arg1 * beginAction:('Arg1 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * beginAction:('Arg1 * 'Arg2 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * arg3:'Arg3 * beginAction:('Arg1 * 'Arg2 * 'Arg3 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromContinuations : callback:(('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T>
static member Ignore : computation:Async<'T> -> Async<unit>
static member OnCancel : interruption:(unit -> unit) -> Async<IDisposable>
static member Parallel : computations:seq<Async<'T>> -> Async<'T []>
static member RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:CancellationToken -> 'T
static member Sleep : millisecondsDueTime:int -> Async<unit>
static member Start : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions * ?cancellationToken:CancellationToken -> Task<'T>
static member StartChild : computation:Async<'T> * ?millisecondsTimeout:int -> Async<Async<'T>>
static member StartChildAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions -> Async<Task<'T>>
static member StartImmediate : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartWithContinuations : computation:Async<'T> * continuation:('T -> unit) * exceptionContinuation:(exn -> unit) * cancellationContinuation:(OperationCanceledException -> unit) * ?cancellationToken:CancellationToken -> unit
static member SwitchToContext : syncContext:SynchronizationContext -> Async<unit>
static member SwitchToNewThread : unit -> Async<unit>
static member SwitchToThreadPool : unit -> Async<unit>
static member TryCancelled : computation:Async<'T> * compensation:(OperationCanceledException -> unit) -> Async<'T>
static member CancellationToken : Async<CancellationToken>
static member DefaultCancellationToken : CancellationToken

Full name: Microsoft.FSharp.Control.Async

--------------------
type Async<'T>

Full name: Microsoft.FSharp.Control.Async<_>
static member Async.Sleep : millisecondsDueTime:int -> Async<unit>
Random.Next() : int
Random.Next(maxValue: int) : int
Random.Next(minValue: int, maxValue: int) : int
val reply : msg:'a -> MessageHandler<ActorCell<'b>,unit>

Full name: Cricket.Message.reply
val bRef : ActorRef

Full name: Diagnostics_tracing.bRef
custom operation: inherits (ActorConfiguration<'a>)

Calls ActorConfigurationBuilder.Inherits
custom operation: name (string)

Calls ActorConfigurationBuilder.Name
Multiple items
module Actor

from Cricket

--------------------
type Actor<'a> =
  interface IDisposable
  interface IActor<'a>
  interface IActor
  new : defn:ActorConfiguration<'a> -> Actor<'a>
  override ToString : unit -> string
  member Ref : ActorRef

Full name: Cricket.Actor<_>

--------------------
new : defn:ActorConfiguration<'a> -> Actor<'a>
val spawn : config:ActorConfiguration<'a> -> ActorRef

Full name: Cricket.Actor.spawn
val cRef : ActorRef

Full name: Diagnostics_tracing.cRef
val frontEnd : ActorRef

Full name: Diagnostics_tracing.frontEnd
val middleTier : Lazy<ActorSelection>
val loop : (Map<Guid,(ActorSelection * string list)> -> MessageHandler<ActorCell<Message>,unit>)
val state : Map<Guid,(ActorSelection * string list)>
val sender : ActorSelection
val sender : unit -> MessageHandler<ActorCell<'a>,ActorSelection>

Full name: Cricket.Message.sender
val post : targets:'a -> msg:'b -> MessageHandler<ActorCell<'c>,unit>

Full name: Cricket.Message.post
Multiple items
module Map

from Microsoft.FSharp.Collections

--------------------
type Map<'Key,'Value (requires comparison)> =
  interface IEnumerable
  interface IComparable
  interface IEnumerable<KeyValuePair<'Key,'Value>>
  interface ICollection<KeyValuePair<'Key,'Value>>
  interface IDictionary<'Key,'Value>
  new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
  member Add : key:'Key * value:'Value -> Map<'Key,'Value>
  member ContainsKey : key:'Key -> bool
  override Equals : obj -> bool
  member Remove : key:'Key -> Map<'Key,'Value>
  ...

Full name: Microsoft.FSharp.Collections.Map<_,_>

--------------------
new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
val add : key:'Key -> value:'T -> table:Map<'Key,'T> -> Map<'Key,'T> (requires comparison)

Full name: Microsoft.FSharp.Collections.Map.add
member Map.TryFind : key:'Key -> 'Value option
val s : ActorSelection
val h : string
val remove : key:'Key -> table:Map<'Key,'T> -> Map<'Key,'T> (requires comparison)

Full name: Microsoft.FSharp.Collections.Map.remove
val empty<'Key,'T (requires comparison)> : Map<'Key,'T> (requires comparison)

Full name: Microsoft.FSharp.Collections.Map.empty
val client : ActorRef

Full name: Diagnostics_tracing.client
val frontend : Lazy<ActorSelection>
val msg : string
Guid.NewGuid() : Guid
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
union case Option.None: Option<'T>
val rawTraces : TraceEntry []

Full name: Diagnostics_tracing.rawTraces
member InMemoryTraceWriter.GetTraces : unit -> TraceEntry []
val timeLine : unit -> (string * string * DateTime * DateTime) list

Full name: Diagnostics_tracing.timeLine
module Seq

from Microsoft.FSharp.Collections
val groupBy : projection:('T -> 'Key) -> source:seq<'T> -> seq<'Key * seq<'T>> (requires equality)

Full name: Microsoft.FSharp.Collections.Seq.groupBy
val t : TraceEntry
TraceEntry.SpanId: uint64
val collect : mapping:('T -> #seq<'U>) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.collect
val ts : seq<TraceEntry>
val x : TraceEntry
val choose : chooser:('T -> 'U option) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.choose
val t : seq<TraceEntry>
val t : TraceEntry list
val sortBy : projection:('T -> 'Key) -> source:seq<'T> -> seq<'T> (requires comparison)

Full name: Microsoft.FSharp.Collections.Seq.sortBy
TraceEntry.Timestamp: int64
val toList : source:seq<'T> -> 'T list

Full name: Microsoft.FSharp.Collections.Seq.toList
val h : TraceEntry
TraceEntry.Actor: ActorPath
property ActorPath.Path: string
TraceEntry.Sender: ActorPath
Multiple items
type DateTime =
  struct
    new : ticks:int64 -> DateTime + 10 overloads
    member Add : value:TimeSpan -> DateTime
    member AddDays : value:float -> DateTime
    member AddHours : value:float -> DateTime
    member AddMilliseconds : value:float -> DateTime
    member AddMinutes : value:float -> DateTime
    member AddMonths : months:int -> DateTime
    member AddSeconds : value:float -> DateTime
    member AddTicks : value:int64 -> DateTime
    member AddYears : value:int -> DateTime
    ...
  end

Full name: System.DateTime

--------------------
DateTime()
   (+0 other overloads)
DateTime(ticks: int64) : unit
   (+0 other overloads)
DateTime(ticks: int64, kind: DateTimeKind) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, calendar: Globalization.Calendar) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, kind: DateTimeKind) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, calendar: Globalization.Calendar) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int, kind: DateTimeKind) : unit
   (+0 other overloads)
val failwithf : format:Printf.StringFormat<'T,'Result> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.failwithf
val toArray : source:seq<'T> -> 'T []

Full name: Microsoft.FSharp.Collections.Seq.toArray
val data : (string * string * DateTime * DateTime) list

Full name: Diagnostics_tracing.data
Fork me on GitHub