-
Notifications
You must be signed in to change notification settings - Fork 154
Feature request: add circular buffer to hold logs #3589
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
@dreamorosi, Would love to work on this issue |
Hi @VatsalGoel3, sounds good! I see you've already opened a PR, so let's continue the discussion there. |
This issue is now closed. Please be mindful that future comments are hard for our team to see. If you need more assistance, please either tag a team member or open a new issue that references this one. If you wish to keep having a conversation with other community members under this issue feel free to do so. |
This is now released under v2.15.0 version! |
Use case
As part of the implementation of the log buffering feature for Logger we need to implement logic that allows the Logger to add log entries to a buffer and later retrieve them. This buffer logic should be able to hold one or more buffers of logs with each buffer being tied to a request.
For example, assuming the following code:
The following two requests:
_X_AMZN_TRACE_ID=abcd
; event{ userId: 'Alice' }
_X_AMZN_TRACE_ID=efgh
; event{ userId: 'Bob' }
Should allow the Logger class to create two buffers, one for each request, in which to store the respective log of each request. Logs of different requests should never end up in the same buffer:
['abcd', [{ userId: 'Alice' }]]
['efgh', [{ userId: 'Bob' }]]
For this part of the implementation we will focus on the data structures that will allow us to create and hold these buffers, how the logs are added to the buffers and what identifies requests are points that will be tackled in separate issues.
For a full overview of the feature, please refer to this RFC (#3410) and specifically to this comment for the final spec.
Solution/User Experience
This should be a standalone module under
packages/logger/src/
in which we'll add the logic needed to create a circular buffer.To keep the buffer decoupled from the rest, consumers of this buffer should only: 1/ set a max size in bytes, 2/ optionally provide an
onBufferOverflow()
callback function that is called by the buffer when the buffer was full, and 3/ be able to set, get, delete items at a specific key.Since we need to create one buffer for each AWS Lambda invocation, my current line of thinking is to use a
Set
to hold the logs of a request (aka the buffer), and aMap
to hold these buffers. Since these two data structures don't provide a way to keep track of size in bytes nor an eviction mechanism, I was thinking we could extend them rather than starting from scratch.The first of the two pieces is the buffer itself, below is some pseudo code of how I think it could work:
The key features of this extended set are:
0
and every time an item is added, the item size is added to the tallyshift
(name borrowed from the analogous array method) that gets the first element in the set and deletes itI also added a custom data structure called
SizedItem
, its main purpose is to centralize the logic to calculate the size of an item, and reuse it as much as possible rather than recalculate it.The second part is the map of buffers that holds all the request buffers, again below is some pseudo code:
The key features of this second data structure are:
maxBytesSize
parameter that represents the max size a buffer can reachI have not tested these implementations at all, so they might be broken or I might be missing something, so whoever implements this please feel free to deviate from it. If you do, I'd still be curious to discuss the reasoning and benefits, but other than that it's fine.
Also, I imagine that calculating the size of items might require different treatments depending on the type of the item stored. Ideally we should be able to store objects (i.e.
{ message: 'hello world', age: 42 }
), but if that complicates things too much we can also just assume everything is a string and move on (i.e.'{"message":"hello world","age"42}'
). The decision for this topic is left to the implementer, but I'd say let's prioritize completion over versatility at this stage, since we already know we'll be storing logs - the question is just whether we're storing them serialized or not.In terms of unit tests for these new data structures, you can use these as reference for an idea of which cases we should handle.
Alternative solutions
Acknowledgment
Future readers
Please react with 👍 and your use case to help us understand customer demand.
The text was updated successfully, but these errors were encountered: