Mantenha tudo organizado com as coleções
Salve e categorize o conteúdo com base nas suas preferências.
Fazer o download dos dados do perfil
Neste documento, descrevemos como fazer o download dos dados do perfil para o
sistema local e como recuperar programaticamente os dados do perfil
usando um aplicativo Go.
Fazer o download de perfis usando o console do Google Cloud
Para fazer o download do perfil exibido no gráfico de chama, clique em Fazer downloadget_app.
O Profiler usa a seguinte convenção de nomenclatura para o arquivo transferido:
Para recuperar dados do perfil, use o método de API ListProfiles. O programa Go de exemplo a seguir demonstra o uso dessa API.
O programa de exemplo cria uma pasta no diretório em que é executado e
gera um conjunto de arquivos pprof numerados. Cada arquivo tem uma convenção de
nomenclatura semelhante a profile000042.pb.gz. Cada diretório contém dados de perfil
e um arquivo de metadados, metadata.csv, que contém informações sobre os
arquivos transferidos por download.
// Sample export shows how ListProfiles API can be used to download
// existing pprof profiles for a given project from GCP.
package main
import (
"bytes"
"context"
"encoding/csv"
"encoding/json"
"flag"
"fmt"
"io"
"log"
"os"
"time"
cloudprofiler "cloud.google.com/go/cloudprofiler/apiv2"
pb "cloud.google.com/go/cloudprofiler/apiv2/cloudprofilerpb"
"google.golang.org/api/iterator"
)
var project = flag.String("project", "", "GCP project ID from which profiles should be fetched")
var pageSize = flag.Int("page_size", 100, "Number of profiles fetched per page. Maximum 1000.")
var pageToken = flag.String("page_token", "", "PageToken from a previous ListProfiles call. If empty, the listing will start from the begnning. Invalid page tokens result in error.")
var maxProfiles = flag.Int("max_profiles", 1000, "Maximum number of profiles to fetch across all pages. If this is <= 0, will fetch all available profiles")
const ProfilesDownloadedSuccessfully = "Read max allowed profiles"
// This function reads profiles for a given project and stores them into locally created files.
// The profile metadata gets stored into a 'metdata.csv' file, while the individual pprof files
// are created per profile.
func downloadProfiles(ctx context.Context, w io.Writer, project, pageToken string, pageSize, maxProfiles int) error {
client, err := cloudprofiler.NewExportClient(ctx)
if err != nil {
return err
}
defer client.Close()
log.Printf("Attempting to fetch %v profiles with a pageSize of %v for %v\n", maxProfiles, pageSize, project)
// Initial request for the ListProfiles API
request := &pb.ListProfilesRequest{
Parent: fmt.Sprintf("projects/%s", project),
PageSize: int32(pageSize),
PageToken: pageToken,
}
// create a folder for storing profiles & metadata
profilesDirName := fmt.Sprintf("profiles_%v", time.Now().Unix())
if err := os.Mkdir(profilesDirName, 0750); err != nil {
log.Fatal(err)
}
// create a file for storing profile metadata
metadata, err := os.Create(fmt.Sprintf("%s/metadata.csv", profilesDirName))
if err != nil {
return err
}
defer metadata.Close()
writer := csv.NewWriter(metadata)
defer writer.Flush()
writer.Write([]string{"File", "Name", "ProfileType", "Target", "Duration", "Labels"})
profileCount := 0
// Keep calling ListProfiles API till all profile pages are fetched or max pages reached
profilesIterator := client.ListProfiles(ctx, request)
for {
// Read individual profile - the client will automatically make API calls to fetch next pages
profile, err := profilesIterator.Next()
if err == iterator.Done {
log.Println("Read all available profiles")
break
}
if err != nil {
return fmt.Errorf("error reading profile from response: %w", err)
}
profileCount++
filename := fmt.Sprintf("%s/profile%06d.pb.gz", profilesDirName, profileCount)
err = os.WriteFile(filename, profile.ProfileBytes, 0640)
if err != nil {
return fmt.Errorf("unable to write file %s: %w", filename, err)
}
fmt.Fprintf(w, "deployment target: %v\n", profile.Deployment.Labels)
labelBytes, err := json.Marshal(profile.Labels)
if err != nil {
return err
}
err = writer.Write([]string{filename, profile.Name, profile.Deployment.Target, profile.Duration.String(), string(labelBytes)})
if err != nil {
return err
}
if maxProfiles > 0 && profileCount >= maxProfiles {
fmt.Fprintf(w, "result: %v", ProfilesDownloadedSuccessfully)
break
}
if profilesIterator.PageInfo().Remaining() == 0 {
// This signifies that the client will make a new API call internally
log.Printf("next page token: %v\n", profilesIterator.PageInfo().Token)
}
}
return nil
}
func main() {
flag.Parse()
// validate project ID
if *project == "" {
log.Fatalf("No project ID provided, please provide the GCP project ID via '-project' flag")
}
var writer bytes.Buffer
if err := downloadProfiles(context.Background(), &writer, *project, *pageToken, *pageSize, *maxProfiles); err != nil {
log.Fatal(err)
}
log.Println("Finished reading all profiles")
}
O programa de exemplo aceita os seguintes argumentos da linha de comando:
project: o projeto do qual os perfis são recuperados. Obrigatório.
page_size: o número máximo de perfis recuperados por chamada de API. O
valor máximo de page_size é 1.000. Quando não especificado, este campo é definido como 100.
page_token: um token de string gerado por uma execução anterior do programa para retomar os downloads. Opcional.
max_profiles: o número máximo de perfis a serem recuperados. Se um número inteiro não positivo
for fornecido, o programa vai tentar recuperar todos os perfis.
Opcional.
Executar o aplicativo de amostra
Para executar o aplicativo de amostra, faça o seguinte:
Mude para o diretório que contém o programa de amostra:
cd golang-samples/profiler/export
Execute o programa depois de substituir YOUR_GCP_PROJECT pelo ID do seu
projeto do Google Cloud:
go run main.go -project YOUR_GCP_PROJECT -page_size 1000 -max_profiles 10000
O programa pode levar um tempo considerável para ser concluído. Depois de recuperar a página atual, o programa gera um token para a próxima página. É possível usar o token para retomar o processo se o programa for interrompido.