Download profile data
This document describes how you can download your profile data to your local system, and how you can programmatically retrieve profile data by using a Go application.
Download profiles by using the Google Cloud console
To download the profile displayed in the flame graph, click Download get_app.
Profiler uses the following naming convention for the downloaded file:
profiler_[SERVICE_NAME]_[PROFILE_TYPE]_[FROM_DATE]_[TO_DATE]_[ZONE]_[VERSION].pb.gz
In this expression:
SERVICE_NAMEcontains your Service selectionPROFILE_TYPEcontains your Profile type selectionFROM_DATEandTO_DATEcontains your time-range specificationsZONEcontains your Zone selectionVERSIONcontains your Version selection
Example: profiler_docdemo-service_HEAP_2018年04月22日T20_25_31Z_2018年05月22日T20_25_31Z_us-east1-c.pb.gz
Download profiles programmatically
To retrieve profile data, use the ListProfiles API method. The following
sample Go program demonstrates the use of this API.
The sample program creates a folder in the directory from where it is run, and
generates a set of numbered pprof files. Each file has a naming
convention similar to profile000042.pb.gz. Each directory contains profile data
and a metadata file - metadata.csv, which contains information about the
downloaded files.
// Sample export shows how ListProfiles API can be used to download
// existing pprof profiles for a given project from GCP.
packagemain
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"
)
varproject=flag.String("project","","GCP project ID from which profiles should be fetched")
varpageSize=flag.Int("page_size",100,"Number of profiles fetched per page. Maximum 1000.")
varpageToken=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.")
varmaxProfiles=flag.Int("max_profiles",1000,"Maximum number of profiles to fetch across all pages. If this is <= 0, will fetch all available profiles")
constProfilesDownloadedSuccessfully="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.
funcdownloadProfiles(ctxcontext.Context,wio.Writer,project,pageTokenstring,pageSize,maxProfilesint)error{
client,err:=cloudprofiler.NewExportClient (ctx)
iferr!=nil{
returnerr
}
deferclient.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())
iferr:=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))
iferr!=nil{
returnerr
}
defermetadata.Close()
writer:=csv.NewWriter(metadata)
deferwriter.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 ()
iferr==iterator.Done{
log.Println("Read all available profiles")
break
}
iferr!=nil{
returnfmt.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)
iferr!=nil{
returnfmt.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)
iferr!=nil{
returnerr
}
err=writer.Write([]string{filename,profile.Name,profile.Deployment.Target,profile.Duration.String(),string(labelBytes)})
iferr!=nil{
returnerr
}
ifmaxProfiles > 0 && profileCount>=maxProfiles{
fmt.Fprintf(w,"result: %v",ProfilesDownloadedSuccessfully)
break
}
ifprofilesIterator.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)
}
}
returnnil
}
funcmain(){
flag.Parse()
// validate project ID
if*project==""{
log.Fatalf("No project ID provided, please provide the GCP project ID via '-project' flag")
}
varwriterbytes.Buffer
iferr:=downloadProfiles(context.Background(),&writer,*project,*pageToken,*pageSize,*maxProfiles);err!=nil{
log.Fatal(err)
}
log.Println("Finished reading all profiles")
}
The sample program accepts the following command line arguments:
project: The project from which the profiles are retrieved. Required.page_size: The maximum number of profiles retrieved per API call. The maximum value ofpage_sizeis 1000. When not specified, this field is set to 100.page_token: A string token generated by a previous run of the program to resume downloads. Optional.max_profiles: The maximum number of profiles to retrieve. If a non-positive integer is provided, then the program attempts to retrieve all profiles.
Optional.
Run the sample application
To run the sample application, do the following:
Clone the repository:
gitclonehttps://github.com/GoogleCloudPlatform/golang-samples.gitChange to the directory that contains the sample program:
cdgolang-samples/profiler/exportRun the program after you replace YOUR_GCP_PROJECT with the ID of your Google Cloud project:
gorunmain.go-projectYOUR_GCP_PROJECT-page_size1000-max_profiles10000
The program might take considerable time to complete. The program outputs a token for the next page after retrieving the current page. You can use the token to resume the process if the program is interrupted.
View the downloaded profiles
To read a downloaded file, which is written in the
serialized protocol buffer format, use the open source
pprof tool.