Having the basic data structures ready, a function to insert data is required. As previously stated, a skip list can only work if the values are somehow comparable and follow an ascending order. This makes sense: skipping ahead is only useful if you know where you are going!
A very efficient way to create a sorted list is by doing a sorted insert (sometimes called an insertion sort). Commonly, this would add some complexity to the insert logic to find the correct place for the node. However, since a timestamp is naturally ascending and a comparable value, this version of the transaction log works without a sophisticated insert, thereby requiring fewer tests and fewer headaches when reading it a year down the road.
In fact, this means reusing some code from earlier sections is entirely possible:
pub fn append(&mut self, offset: u64, value: String) {
let level = 1 + if self.head.is_none() {
self.max_level // use the maximum level for the first node
} else...