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

Large postgres logs #105

Merged
merged 10 commits into from
Oct 3, 2024
Merged

Conversation

philrhurst
Copy link
Collaborator

gathering large Postgres files may pose a challenge for some systems. This change stores the file on disk, compares the filesize with the remote, and adds the local file to the tar. It has error handling to allow a support export to be generated when there are issues with gathering PG logs.

Philip Hurst added 2 commits September 24, 2024 17:37
Large Postgres files may pose a challenge for some systems. This change stores the file on disk, compares the filesize with the remote, and adds the local file to the tar. It has error handling to allow a support export to be generated when there are issues with gathering PG logs.
internal/cmd/export.go Outdated Show resolved Hide resolved
internal/cmd/export.go Outdated Show resolved Hide resolved
Create a unique sudirectory in outputDir (matching the unique timestamp) so that local files are logically separate from other files. Adding messaging and error handling so a user understands.
internal/cmd/export.go Outdated Show resolved Hide resolved
internal/cmd/export.go Outdated Show resolved Hide resolved
Comment on lines 1861 to 1876
req := clientset.CoreV1().RESTClient().
Get().
Resource("pods").
Name(podName).
Namespace(namespace).
SubResource("exec").
Param("container", containerName).
Param("command", "cat").
Param("command", remotePath).
Param("stderr", "true").
Param("stdout", "true")

exec, err := remotecommand.NewSPDYExecutor(config, "GET", req.URL())
if err != nil {
return fmt.Errorf("failed to initialize SPDY executor: %w", err)
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could we use the util.NewPodExecutor to set this command up?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The problem I've had there is the current flow assumes the contents will be held in memory. I couldn't figure out how to use the current flow to pass to *os.File - Definitely a limitation on my part, so feedback is welcome

Copy link
Collaborator

Choose a reason for hiding this comment

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

hmmm, NewPodExecutor returns a func that takes stdout, stderr io.Writer, and I'm not against writing a specific function for this executor, like

func (exec Executor) copyFile(source string, destination *os.File) (string, error) {
	var stderr bytes.Buffer
        command := fmt.Sprintf("cat %s", source)
	err := exec(nil, &desination, &stderr, "bash", "-ceu", "--", command)
	return stderr.String(), err
}

That's a slight variation on the catFile func, the main difference being that it sets the output to the file (I think) and doesn't return a stdout. Not sure that would work, but that's my first thought.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

one slight change &destination to destination, but I think this works.

func (exec Executor) copyFile(source string, destination *os.File) (string, error) {
	var stderr bytes.Buffer
	command := fmt.Sprintf("cat %s", source)
	err := exec(nil, destination, &stderr, "bash", "-ceu", "--", command)
	return stderr.String(), err
}

Comment on lines 1963 to 1982
req := clientset.
CoreV1().
RESTClient().
Post().
Namespace(namespace).
Resource("pods").
Name(podName).
SubResource("exec").
Param("container", containerName).
Param("command", "stat").
Param("command", "-c").
Param("command", "%s").
Param("command", filePath).
Param("stderr", "true").
Param("stdout", "true")

exec, err := remotecommand.NewSPDYExecutor(config, "GET", req.URL())
if err != nil {
return 0, fmt.Errorf("could not initialize SPDY executor for stat: %w", err)
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ditto question re: util.NewPodExecutor

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I refactored this one to use the bashCommand function and executor. This one is easier because it's a simple stat command.

}

// ConvertBytes converts a byte size (int64) into a human-readable format.
func ConvertBytes(bytes int64) string {
Copy link
Collaborator

Choose a reason for hiding this comment

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

We're not exporting this command for another package to use, so convertBytes should be fine. (Also here's a case where I think tests would do some work as documentation.)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I renamed this one

}

// compare file sizes
localFileInfo, err := os.Stat(localPath)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Here we use os.Stat(FILE) and on line 1912 we use file.Stat() -- they're functionally the same, right? Not a blocker, just curious if we could use the same func twice. (I'm looking at the code for the two functions and they're not identical in the way I sort of thought they might be, though they both end up calling the fillFileStatFromSys helper func.)

Copy link
Collaborator

@benjaminjb benjaminjb left a comment

Choose a reason for hiding this comment

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

No blockers, just one last question

@philrhurst philrhurst merged commit edbf76e into CrunchyData:main Oct 3, 2024
7 checks passed
@philrhurst philrhurst deleted the large-postgres-logs branch October 3, 2024 16:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants