This terminology is rooted in the history of OpenGL. What's important to remember is that, for most of the GL versions which are relevant here, OpenGL was evolved incrementally and by adding new functionality to an already existing API rather than changing the API.
The first version of OpenGL had none of these object types. Drawing was achieved by issuing multiple glBegin/glEnd calls, and one problem with this model was that it was very inefficient, in terms of function call overhead.
OpenGL 1.1 took the first steps to address this by introducing vertex arrays. Instead of directly specifying vertex data you could now source it from C/C++ arrays - hence the name. So a vertex array is just that - an array of vertices and the GL state required to specify them.
The next major evolution came with GL 1.5 and allowed storing vertex array data in GPU memory rather than in system ("client-side") memory. A weakness of the GL 1.1 vertex array specification was that the full set of vertex data had to be transferred to the GPU each time you wanted to use it; if it was already on the GPU then this transfer could be avoided and potential performance gains achieved.
So a new type of GL object was created to allow storing of this data on the GPU. Just like a texture object is used for storing texture data, a vertex buffer object stores vertex data. This is actually just a special case of a more general buffer object type which may store non-specific data.
The API for using vertex buffer objects was piggy-backed on the already existing vertex arrays API, which is why you see weird things like converting byte offsets to pointers in it. So now we have a vertex arrays API that just stores state, with the data being sourced from buffer objects rather than from in-memory arrays.
This brings us almost to the end of our story. The resulting API was quite verbose when it came to specifying vertex array state, so another avenue of optimization was to create a new object type that collected all of this state together, allowed multiple vertex array state changes in a single API call, and allowed GPUs to potentially perform optimizations due to being able to know what state was going to be used ahead of time.
Enter the vertex array object, which collects all of this together.
So, to summarise, a vertex array started life as a collection of state and data (stored in an array) for drawing with. A vertex buffer replaces the in-memory array storage with a GL object type, leaving the vertex array just being state. A vertex array object is just a container object for this state, allowing it to be changed more easily and with fewer API calls.
char* buffer = socketRead();
(pseudocode). The log on the other hand, lives through the entire app lifecycle. So you create an array somewhere and start reading the socket, anytime you get data you write that chunk to the array, giving you a neat list of all the data you received. \$\endgroup\$ – Kevin Nov 1 '18 at 15:12