Repository F# setup
open System
open System.IO
open System.Threading
open System.Threading.Tasks
open Axial
open Axial.Layers
open Axial.Console
open Axial.FileSystem
open Axial.Hosting
open Axial.Hosting.Browser
open Axial.Hosting.Node
open Axial.HttpClient
open Axial.PlatformService
open Axial.Process
open Axial.State
open Axial.Telemetry
open Axial.Telemetry.JavaScriptILog is a deliberately small logging contract: write a message at a level, or write one carrying an exception.
open System
open Axial
open Axial.PlatformService
SystemAxialPlatformServicelet recordAttempt name : Flow<#IHasLog, Never, unit> =
Log.info $"Processing {name}"
recordAttempt: 'a -> Flow<'b,Never,unit>name: 'aAxial.Flow`3Represents a cold workflow that reads an environment, returns a typed result, and is executed explicitly through one of its execution members such as ToTask, ToAsync, or RunSynchronously. The type of the environment dependency. The type of the failure value. The type of the success value.
Axial.PlatformService.IHasLogDeclares that an environment supplies the logging service.
Axial.NeverRepresents an error channel that cannot occur.
unitThe type 'unit', which has only one value "()". This value is special and always uses the representation 'null'. Basic Types
Axial.PlatformService.LogHelpers for the logging service.
info: string -> Flow<'env,'error,unit>Writes an informational log message through an explicit logging service.
Log.trace message
Log.debug message
Log.info message
Log.warning message
Log.error message
Log.critical message
Log.errorExn error message
Log.criticalExn error message
Log.log level message
Log.logException level error messageSupplying the service
Log.live is a no-op logger. That is the deliberate default: a library that logs should not start writing to
somebody's console because they forgot to configure a sink. Wire a real one with Log.fromSink:
let log = Log.fromSink (fun level message -> printfn $"[{level}] {message}")
log: ILogAxial.PlatformService.LogHelpers for the logging service.
fromSink: (LogLevel -> string -> unit) -> ILogCreates a logger from a synchronous sink function. Exceptions are appended to the message text.
level: LogLevelmessage: stringprintfn: Printf.TextWriterFormat<'T> -> 'TPrint to stdout using the given format, and add a newline. The formatter. The formatted result. See Printf.printfn (link: ) for examples.
Log.layer provides the no-op logger; supply your own layer when the application has a sink.
Logging against telemetry
ILog is the service a workflow depends on to say something. It is not the tracing and metrics story — spans,
metrics, and OpenTelemetry export are covered in observability. The two meet at the
host: an ILog implementation can forward into the same backend the telemetry exporter writes to.
Choose ILog when the workflow itself should emit a message. Choose telemetry when you want the runtime's own
execution structure recorded.
Testing
Assert on log output by collecting it:
let messages = ResizeArray<LogLevel * string>()
let log = Log.fromSink (fun level message -> messages.Add(level, message))
