Logging Events

Coco supports auto-generated logging of events. This includes a detailed description of when a function call starts and finishes; when a signal is dequeued and starts to be processed, and when the processing of that signal completes; and when a timer or unused transition is executed.

For example, consider a function initialise(setting : Bool) that returns true or false to indicate whether the request is successful, and can be called on some component instance controller. The following sequence is an example of the logging output Coco will generate for this function:

> controller: client.initialise{setting=true}
< controller: client.initialise{} -> true

Depending on the implementation of this component, together with the other instances of components within the system, this sequence may be interleaved with other events being logged. See Logging Format for an overview of a description of the format of the logging output.

Coco’s auto-generated logging is optionally able to log the values of parameters, return types, and state parameters, as illustrated in the example above. To use this, the language.standard must be set to 1.2 or above, and generator.cpp.logValues must be set to either of the following:

  • "Always": means that an instance of Log is required for all parameters and return values, or an error will be raised.
  • "WhenAvailable": means that parameters or return values that have a Log instance will be logged. This is the default with the language standard 1.2.

Specific parameters and types can be excluded by marking them with the @noLog attribute, as illustrated in the following examples:

@noLog
external type DoNotLogMe

port AuthHandler {
  function login(username : String, @noLog password : String) : Nil
}

All parameters are logged using the instance of the Log trait. The following table summarises which parameters are logged on which events:

Parameter Type T & &out &mut
Function Call
Return

For example, a function with a parameter of some type T will have its parameter logged when called, whereas a function with an &out parameter would only have its parameter logged upon the return event.

Logging Format

Coco provides a standardised logging format for the auto-generated logging. This logging format is designed to be both human and machine-readable, and is also consistent between the different code generators that Coco has (e.g. the output is produced identically by both the C and C++ generators).

syntaxLogging Format
«event marker» «component» [ («state») ] : «port» . «event» «parameter list» [-> «parameter value»]

«event marker» := > | <

«component» := «path»

«state» := «identifier»[«parameter list»]

«port» := «path»

«event» := «identifier»

«parameter list» := («parameter values») | { «parameter pairs» }

«parameter pair» := «identifier» = «parameter value»

«parameter value» ::=
  «integer»
  | «character»
  | «string»
  | `«any»`
  | _
  | «identifier» [«parameter list»]
  | { «parameter pair» }

«path» :=
  «identifier»
  | «path» '[' «integer» ']'
  | «path» '.' «identifier»

where:

  • > denotes an event starting.
  • < denotes an event finishing.
  • «component» is the component’s name, including array indicies.
  • «port» is the port instance’s name.
  • «event» gives the name of the function or signal.
  • «parameter value» denotes one of the Coco-encoded values created using the Log trait.
  • # denotes a commented line.

For example, consider the function onOff(turnOn : Bool) which can be called on the component instance lightSource to turn a light on or off (as captured by the parameter). The log output for calling onOff(true) is captured as follows:

> lightSource: client.onOff{turnOn=true}

Suppose the function onOff() returned Result<Nil, Int>, and in this case returned the value Error(1). The resulting log output for the return event would be as follows:

< lightSource: client.onOff{} -> Error(1)

The log output also captures the state that the corresponding component is in when the event is logged, for example:

< light (OperationalFlashing): client.flashingOn()