# ARC-28: Structured event logging

[ARC-28](https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0028.md) provides a methodology for structured logging by Algorand smart contracts. It introduces the concept of Events, where data contained in logs may be categorized and structured.

Each Event is identified by a unique 4-byte identifier derived from its `Event Signature`. The Event Signature is a UTF-8 string comprised of the event’s name, followed by the names of the [ARC-4](https://dev.algorand.co/algokit/languages/python/lg-arc4/) data types contained in the event, all enclosed in parentheses (`EventName(type1,type2,...)`) e.g.:

```
Swapped(uint64,uint64)
```

Events are emitted by including them in the [log output](https://dev.algorand.co/algokit/languages/python/lg-logs/). The metadata that identifies the event should then be included in the ARC-4 contract output so that a calling client can parse the logs to parse the structured data out. This part of the ARC-28 spec isn’t yet implemented in Algorand Python, but it’s on the roadmap.

## Emitting Events

[Section titled “Emitting Events”](https://dev.algorand.co/algokit/languages/python/lg-arc28/#emitting-events)

To emit an ARC-28 event in Algorand Python you can use the `emit` function, which appears in the `algopy.arc4` namespace for convenience since it heavily uses ARC-4 types and is essentially an extension of the ARC-4 specification. This function takes care of encoding the event payload to conform to the ARC-28 specification and there are 3 overloads:

- An [ARC-4 struct](https://dev.algorand.co/algokit/languages/python/lg-arc4/#structs), from which the name of the struct will be used as the event name and the struct parameters will be used as the event fields - `arc4.emit(Swapped(a, b))`
- An event signature as a [string literal (or module variable)](https://dev.algorand.co/algokit/languages/python/lg-types/), followed by the values - `arc4.emit("Swapped(uint64,uint64)", a, b)`
- An event name as a [string literal (or module variable)](https://dev.algorand.co/algokit/languages/python/lg-types/), followed by the values - `arc4.emit("Swapped", a, b)`

Here’s an example contract that emits events:

```
from algopy import ARC4Contract, arc4

class Swapped(arc4.Struct):

a: arc4.UInt64

b: arc4.UInt64

class EventEmitter(ARC4Contract):

@arc4.abimethod

def emit_swapped(self, a: arc4.UInt64, b: arc4.UInt64) -> None:

arc4.emit(Swapped(b, a))

arc4.emit("Swapped(uint64,uint64)", b, a)

arc4.emit("Swapped", b, a)
```

It’s worth noting that the ARC-28 event signature needs to be known at compile time so the event name can’t be a dynamic type and must be a static string literal or string module constant. If you want to emit dynamic events you can do so using the [`log` method](https://dev.algorand.co/algokit/languages/python/lg-logs/), but you’d need to manually construct the correct series of bytes and the compiler won’t be able to emit the ARC-28 metadata so you’ll need to also manually parse the logs in your client.

Examples of manually constructing an event:

```
# This is essentially what the `emit` method is doing, noting that a,b need to be encoded

#   as a tuple so below (simple concat) only works for static ARC-4 types

log(arc4.arc4_signature("Swapped(uint64,uint64)"), a, b)

# or, if you wanted it to be truly dynamic for some reason,

#   (noting this has a non-trivial opcode cost) and assuming in this case

#   that `event_suffix` is already defined as a `String`:
event_name = String("Event") + event_suffix

event_selector = op.sha512_256((event_name + "(uint64)").bytes)[:4]

log(event_selector, UInt64(6))
```
