// 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")}
示例程序接受以下命令行实参:
project:从中检索配置的项目。必填。
page_size:每次 API 调用检索的个人资料数量上限。page_size 的最大值为 1000。如果未指定,此字段会设置为 100。
[[["易于理解","easyToUnderstand","thumb-up"],["解决了我的问题","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["很难理解","hardToUnderstand","thumb-down"],["信息或示例代码不正确","incorrectInformationOrSampleCode","thumb-down"],["没有我需要的信息/示例","missingTheInformationSamplesINeed","thumb-down"],["翻译问题","translationIssue","thumb-down"],["其他","otherDown","thumb-down"]],["最后更新时间 (UTC):2025-08-18。"],[],[],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."]]