Skip to content
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

feat(local-ic): stream interaction and container logs #1269

Merged
merged 21 commits into from
Oct 18, 2024

Conversation

Reecepbcups
Copy link
Member

@Reecepbcups Reecepbcups commented Sep 26, 2024

Summary

For the Spawn UI platform, we need a way to get logs from the network -> the users UI. This PR adds support to stream the logs to both the console & a unique file. Then the user can query /logs in the REST api. It will tail the last N lines, and continue to return new data on new interaction.

Further, the container logs for actuals of a container are streamed too. You can use the container ID or the node name itself. much better than docker ps; docker logs <id> -f for API users.

Based on concept here: https://github.com/Reecepbcups/golang_stream

TODO

  • stream docker container logs out as well? (i.e. /container_logs?id=)
  • Remove dumb comments
  • Print tail X lines of logs endpoint (instead of trying to merge them)
  • Select logs by chain-id vs being the container ID (some mapping between)

Copy link

vercel bot commented Sep 26, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

1 Skipped Deployment
Name Status Preview Comments Updated (UTC)
interchaintest-docs ⬜️ Ignored (Inspect) Visit Preview Oct 18, 2024 4:34am

@Reecepbcups Reecepbcups changed the title feat(local-ic): stream logs feat(local-ic): stream interaction and container logs Oct 12, 2024
@Reecepbcups Reecepbcups marked this pull request as ready for review October 16, 2024 18:06
@Reecepbcups Reecepbcups requested a review from a team as a code owner October 16, 2024 18:06
Reecepbcups and others added 2 commits October 16, 2024 13:11
Co-authored-by: Reece Williams <reecepbcups@gmail.com>
Copy link
Member

@jtieri jtieri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had a couple nits around logs and a couple questions but otherwise the changes look good.

Although it is out of scope of this PR one thing that jumped out to me is that the StartChain function in start.go is growing to be rather large. There are a few places where logic could be broken out into separate functions.

Dockerfile.local-interchain Show resolved Hide resolved
local-interchain/interchain/start.go Show resolved Hide resolved
local-interchain/interchain/start.go Outdated Show resolved Hide resolved
local-interchain/interchain/start.go Outdated Show resolved Hide resolved
local-interchain/interchain/start.go Outdated Show resolved Hide resolved
"go.uber.org/zap"
)

var removeColorRegex = regexp.MustCompile("\x1b\\[[0-9;]*m")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this necessary because certain operating systems or terminals cannot render the colors in the logs?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is being forwarded over a REST api, it is always the case. So most users parsing that data don't care about. We may in the future want to parse out the colors which is why it is possible to opt out and see those ASNI escape sequences

}

for {
buf := make([]byte, 8*1024)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What was the reasoning for instantiating the slice with this specific value? Does changing this value break anything? If so a comment regarding the reason for this specific size could be helpful.

Copy link
Member Author

@Reecepbcups Reecepbcups Oct 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1024 is the standard. Due to the size of some JSON blobs sent through (relayer), it was exceeding that limit for Galen. Causing parsing issues

It was exceeding the size for some relayer JSON blobs for Galen. He was unable to parse it since it came in multiple chunks. I wanted to ensure we have enough of a buffer and 8192 felt like a good spot (21024 was still too small, I am sure 4 would have been fine but increased just to be sure since the data sent it relative small and controlled anyways)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessary but this is the type of decision that can be helpful to document via a comment. You never know when someone is going to come across and naively change values without understanding what the implications are.

var removeColorRegex = regexp.MustCompile("\x1b\\[[0-9;]*m")

type ContainerStream struct {
ctx context.Context
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a specific reason we have to use a Context as a field member of this struct vs. piping a Context into the StreamContainer method or wherever a Context is needed for the ContainerStream?

It's typically more idiomatic to pass a Context around vs. storing one inside of a struct type

One of the exceptions to this rule are typically when you have an external request that starts a background process/operation.

Edit: After reading the rest of the code it seems like that is what may be happening here when a user makes a request to /container_logs so this may be a correct usage of context in a struct but figured I would ask for clarity.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tldr; better Dev UX for the same relative solution

It's cleaner than having to write methods return func(w http.ResponseWriter, req *http.Request) signatures just for ctx to be passed in in a wrapped type.

Current:

r.HandleFunc("/container_logs", containerStream.StreamContainer)

Would be required change

r.HandleFunc("/container_logs", containerStream.handleStreamContainer(ctx))

func (cs *ContainerStream) handleStreamContainer(ctx context) func(w http.ResponseWriter, req *http.Request) {

   return func(w http.ResponseWriter, req *http.Request) {
      // all the same logic here, just wrapped now
    }
}

ctx is only used for timeout limits and set on startup. So any runtime changes are unaffected in either approach - and the first approach is just net easier for a new contributor to wrap their head around.

local-interchain/interchain/handlers/log_stream.go Outdated Show resolved Hide resolved
local-interchain/interchain/handlers/log_stream.go Outdated Show resolved Hide resolved
@Reecepbcups Reecepbcups merged commit bfeb32a into main Oct 18, 2024
19 of 20 checks passed
@Reecepbcups Reecepbcups deleted the reece/local-ic-stream-logs branch October 18, 2024 19:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants