At the low level, you can get this information from
/sys/block/X/stat, which is documented here.
Example content looks like:
10465 3250 759844 27528 4400 2983 546848 66306 0 9754 93792
The fields we want are columns 1 & 3 for reads, and 5 & 7 for writes.
The calculation method is the same for both, so I'll just discuss reads.
Column 1 is the number of reads (which you stated you're already able to monitor), and column 3 is the number of sectors read. A sector is 512 bytes. So with these to calculate the size of the reads, you just do
$col3 * 512 / $col1.
The numbers in this file are the total since disk came online. So to calculate the average read size over a period of time, you just read the file twice, and calculate with:
($col3_t2 - $col3_t1) * 512 / ($col1_t2 - $col1_t1).
Note that the above method gives you the size of the OPs performed at the application level (description is not exact, but close enough). The kernel can merge multiple operations together so the number of operations performed on the disk is smaller. The calculation for this is:
$col3 * 512 / ($col1 - $col2). And to get the value over a span of time:
($col3_t2 - $col3_t1) * 512 / (($col1_t2 - $col1_t1) - ($col2_t2 - $col2_t1))
iostat can give you the value as well, but less accurately. It doesn't differentiate writes or reads, and it only gives you the value in sectors, not bytes (so again, multiply by 512).
But the command is
iostat -x -d, and the column to look at is