Stay organized with collections
Save and categorize content based on your preferences.
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 Downloadget_app.
Profiler uses the following naming convention for the
downloaded file:
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.packagemainimport("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 APIrequest:=&pb.ListProfilesRequest{Parent:fmt.Sprintf("projects/%s",project),PageSize:int32(pageSize),PageToken:pageToken,}// create a folder for storing profiles & metadataprofilesDirName:=fmt.Sprintf("profiles_%v",time.Now().Unix())iferr:=os.Mkdir(profilesDirName,0750);err!=nil{log.Fatal(err)}// create a file for storing profile metadatametadata,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 reachedprofilesIterator:=client.ListProfiles(ctx,request)for{// Read individual profile - the client will automatically make API calls to fetch next pagesprofile,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 internallylog.Printf("next page token: %v\n",profilesIterator.PageInfo().Token)}}returnnil}funcmain(){flag.Parse()// validate project IDif*project==""{log.Fatalf("No project ID provided, please provide the GCP project ID via '-project' flag")}varwriterbytes.Bufferiferr:=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 of page_size is 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.
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.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Hard to understand","hardToUnderstand","thumb-down"],["Incorrect information or sample code","incorrectInformationOrSampleCode","thumb-down"],["Missing the information/samples I need","missingTheInformationSamplesINeed","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-08-28 UTC."],[],[],null,["# Download profile data\n=====================\n\nThis document describes how you can download your profile data to your\nlocal system, and how you can programmatically retrieve profile data by\nusing a Go application.\n\nDownload profiles by using the Google Cloud console\n---------------------------------------------------\n\nTo download the profile displayed in the flame graph,\nclick **Download** *get_app*.\n\nProfiler uses the following naming convention for the\ndownloaded file: \n\n```\nprofiler_[SERVICE_NAME]_[PROFILE_TYPE]_[FROM_DATE]_[TO_DATE]_[ZONE]_[VERSION].pb.gz\n```\n\nIn this expression:\n\n- `SERVICE_NAME` contains your **Service** selection\n- `PROFILE_TYPE` contains your **Profile type** selection\n- `FROM_DATE` and `TO_DATE` contains your time-range specifications\n- `ZONE` contains your **Zone** selection\n- `VERSION` contains your **Version** selection\n\nExample: `profiler_docdemo-service_HEAP_2018-04-22T20_25_31Z_2018-05-22T20_25_31Z_us-east1-c.pb.gz`\n\nDownload profiles programmatically\n----------------------------------\n\n|\n| **Preview**\n|\n|\n| This product or feature is subject to the \"Pre-GA Offerings Terms\" in the General Service Terms section\n| of the [Service Specific Terms](/terms/service-terms#1).\n|\n| Pre-GA products and features are available \"as is\" and might have limited support.\n|\n| For more information, see the\n| [launch stage descriptions](/products#product-launch-stages).\n\nTo retrieve profile data, use the `ListProfiles` API method. The following\nsample Go program demonstrates the use of this API.\n\nThe sample program creates a folder in the directory from where it is run, and\ngenerates a set of numbered [`pprof`](https://github.com/google/pprof) files. Each file has a naming\nconvention similar to `profile000042.pb.gz`. Each directory contains profile data\nand a metadata file - `metadata.csv`, which contains information about the\ndownloaded files. \n\n\n // Sample export shows how ListProfiles API can be used to download\n // existing pprof profiles for a given project from GCP.\n package main\n\n import (\n \t\"bytes\"\n \t\"context\"\n \t\"encoding/csv\"\n \t\"encoding/json\"\n \t\"flag\"\n \t\"fmt\"\n \t\"io\"\n \t\"log\"\n \t\"os\"\n \t\"time\"\n\n \tcloudprofiler \"cloud.google.com/go/cloudprofiler/apiv2\"\n \tpb \"cloud.google.com/go/cloudprofiler/apiv2/cloudprofilerpb\"\n \t\"google.golang.org/api/iterator\"\n )\n\n var project = flag.String(\"project\", \"\", \"GCP project ID from which profiles should be fetched\")\n var pageSize = flag.Int(\"page_size\", 100, \"Number of profiles fetched per page. Maximum 1000.\")\n 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.\")\n var maxProfiles = flag.Int(\"max_profiles\", 1000, \"Maximum number of profiles to fetch across all pages. If this is \u003c= 0, will fetch all available profiles\")\n\n const ProfilesDownloadedSuccessfully = \"Read max allowed profiles\"\n\n // This function reads profiles for a given project and stores them into locally created files.\n // The profile metadata gets stored into a 'metdata.csv' file, while the individual pprof files\n // are created per profile.\n func downloadProfiles(ctx context.Context, w io.Writer, project, pageToken string, pageSize, maxProfiles int) error {\n \tclient, err := cloudprofiler.https://cloud.google.com/go/docs/reference/cloud.google.com/go/cloudprofiler/latest/apiv2.html#cloud_google_com_go_cloudprofiler_apiv2_ExportClient_NewExportClient(ctx)\n \tif err != nil {\n \t\treturn err\n \t}\n \tdefer client.Close()\n \tlog.Printf(\"Attempting to fetch %v profiles with a pageSize of %v for %v\\n\", maxProfiles, pageSize, project)\n\n \t// Initial request for the ListProfiles API\n \trequest := &pb.ListProfilesRequest{\n \t\tParent: fmt.Sprintf(\"projects/%s\", project),\n \t\tPageSize: int32(pageSize),\n \t\tPageToken: pageToken,\n \t}\n\n \t// create a folder for storing profiles & metadata\n \tprofilesDirName := fmt.Sprintf(\"profiles_%v\", time.Now().Unix())\n \tif err := os.Mkdir(profilesDirName, 0750); err != nil {\n \t\tlog.Fatal(err)\n \t}\n \t// create a file for storing profile metadata\n \tmetadata, err := os.Create(fmt.Sprintf(\"%s/metadata.csv\", profilesDirName))\n \tif err != nil {\n \t\treturn err\n \t}\n \tdefer metadata.Close()\n\n \twriter := csv.NewWriter(metadata)\n \tdefer writer.Flush()\n\n \twriter.Write([]string{\"File\", \"Name\", \"ProfileType\", \"Target\", \"Duration\", \"Labels\"})\n\n \tprofileCount := 0\n \t// Keep calling ListProfiles API till all profile pages are fetched or max pages reached\n \tprofilesIterator := client.ListProfiles(ctx, request)\n \tfor {\n \t\t// Read individual profile - the client will automatically make API calls to fetch next pages\n \t\tprofile, err := profilesIterator.https://cloud.google.com/go/docs/reference/cloud.google.com/go/cloudprofiler/latest/apiv2.html#cloud_google_com_go_cloudprofiler_apiv2_ProfileIterator_Next()\n\n \t\tif err == iterator.Done {\n \t\t\tlog.Println(\"Read all available profiles\")\n \t\t\tbreak\n \t\t}\n \t\tif err != nil {\n \t\t\treturn fmt.Errorf(\"error reading profile from response: %w\", err)\n \t\t}\n \t\tprofileCount++\n\n \t\tfilename := fmt.Sprintf(\"%s/profile%06d.pb.gz\", profilesDirName, profileCount)\n \t\terr = os.WriteFile(filename, profile.ProfileBytes, 0640)\n\n \t\tif err != nil {\n \t\t\treturn fmt.Errorf(\"unable to write file %s: %w\", filename, err)\n \t\t}\n \t\tfmt.Fprintf(w, \"deployment target: %v\\n\", profile.Deployment.Labels)\n\n \t\tlabelBytes, err := json.Marshal(profile.Labels)\n \t\tif err != nil {\n \t\t\treturn err\n \t\t}\n\n \t\terr = writer.Write([]string{filename, profile.Name, profile.Deployment.Target, profile.Duration.String(), string(labelBytes)})\n \t\tif err != nil {\n \t\t\treturn err\n \t\t}\n\n \t\tif maxProfiles \u003e 0 && profileCount \u003e= maxProfiles {\n \t\t\tfmt.Fprintf(w, \"result: %v\", ProfilesDownloadedSuccessfully)\n \t\t\tbreak\n \t\t}\n\n \t\tif profilesIterator.PageInfo().Remaining() == 0 {\n \t\t\t// This signifies that the client will make a new API call internally\n \t\t\tlog.Printf(\"next page token: %v\\n\", profilesIterator.https://cloud.google.com/go/docs/reference/cloud.google.com/go/cloudprofiler/latest/apiv2.html#cloud_google_com_go_cloudprofiler_apiv2_ProfileIterator_PageInfo().Token)\n \t\t}\n \t}\n \treturn nil\n }\n\n func main() {\n \tflag.Parse()\n \t// validate project ID\n \tif *project == \"\" {\n \t\tlog.Fatalf(\"No project ID provided, please provide the GCP project ID via '-project' flag\")\n \t}\n \tvar writer bytes.Buffer\n \tif err := downloadProfiles(context.Background(), &writer, *project, *pageToken, *pageSize, *maxProfiles); err != nil {\n \t\tlog.Fatal(err)\n \t}\n \tlog.Println(\"Finished reading all profiles\")\n }\n\nThe sample program accepts the following command line arguments:\n\n- `project`: The project from which the profiles are retrieved. Required.\n- `page_size`: The maximum number of profiles retrieved per API call. The maximum value of `page_size` is 1000. When not specified, this field is set to 100.\n- `page_token`: A string token generated by a previous run of the program to resume downloads. Optional.\n- `max_profiles`: The maximum number of profiles to retrieve. If a non-positive integer is provided, then the program attempts to retrieve all profiles. \n Optional.\n\n### Run the sample application\n\n| **Note:** To successfully run the program, it must be authenticated to Profiler. Authentication can be set up using Application Default Credentials (ADC). For more information, see [Set up ADC for a local development environment](/docs/authentication/set-up-adc-local-dev-environment).\n\nTo run the sample application, do the following:\n\n1. Clone the repository:\n\n git clone https://github.com/GoogleCloudPlatform/golang-samples.git\n\n2. Change to the directory that contains the sample program:\n\n cd golang-samples/profiler/export\n\n3. Run the program after you replace \u003cvar translate=\"no\"\u003eYOUR_GCP_PROJECT\u003c/var\u003e with the ID of your\n Google Cloud project:\n\n go run main.go -project \u003cvar translate=\"no\"\u003eYOUR_GCP_PROJECT\u003c/var\u003e -page_size 1000 -max_profiles 10000\n\nThe program might take considerable time to complete. The program outputs a\ntoken for the next page after retrieving the current page. You can use the\ntoken to resume the process if the program is interrupted.\n\nView the downloaded profiles\n----------------------------\n\nTo read a downloaded file, which is written in the\n[serialized protocol buffer](https://github.com/google/pprof/tree/master/proto) format, use the open source\n[`pprof`](https://github.com/google/pprof) tool."]]