docs.rs failed to build googleads-rs-0.11.0
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Visit the last successful build:
googleads-rs-23.2.0
googleads-rs
Current Version 0.11.0 uses Google Ads API v21
A gRPC client library for Google Ads API, generated automatically from the API definition files.
I use it for my mcc-gaql command line tool to run Google Ads Query Language queries across large number of MCC-linked accounts.
There may be more elegant ways to pull query results from GoogleAdsRow in a reflection-like manner. I couldn't figure it out. So I hand-crafted a GoogleAdsRow.get(path: &str) accessor method for fields which I need.
Example
let client: GoogleAdsServiceClient<InterceptedService<Channel, GoogleAdsAPIAccess>> =
GoogleAdsServiceClient::with_interceptor(api_context.channel.clone(), api_context);
let result: Result<Response<Streaming<SearchGoogleAdsStreamResponse>>, Status> = client
.search_stream(SearchGoogleAdsStreamRequest {
customer_id: customer_id.clone(),
query,
summary_row_setting: 0,
})
.await;
match result {
Ok(response) => {
let mut stream = response.into_inner();
let mut columns: Vec<Vec<String>> = Vec::new();
let mut headers: Option<Vec<String>> = None;
while let Some(item) = stream.next().await {
match item {
Ok(stream_response) => {
let field_mask = stream_response.field_mask.unwrap();
if headers.is_none() {
headers = Some(field_mask.paths.clone());
}
for r in stream_response.results {
let row: GoogleAdsRow = r;
// go through all columns specified in query, pull out string value, and insert into columns
for i in 0..headers.as_ref().unwrap().len() {
let path = &headers.as_ref().unwrap()[i];
let string_val: String = row.get(path).trim_matches('"').to_string();
match columns.get_mut(i) {
Some(v) => {
v.push(string_val);
}
None => {
let v: Vec<String> = vec![string_val];
columns.insert(i, v);
}
}
}
}
}
Err(status) => {
bail!(
"GoogleAdsClient streaming error. Account: {customer_id}, Message: {}, Details: {}",
status.message(),
String::from_utf8_lossy(status.details()).into_owned()
);
}
}
}
}
}
API Upgrade
Run update.sh to update the library for a new Google Ads API version:
- Download latest proto files for new Google Ads API version
- Replace references to old api version in build.rs, lib.rs, and README.md
./utils/update.sh v17
Build process
- build.rs dynamically scans for available proto files, filters them, and feeds them to tonic to generate
protos.rs(following strategy by aquarhead) - lib.rs includes
protos.rs - lib.rs also includes hand-crafted
get()function
pub fn get(&self, field_name: &str) -> String {
match field_name {
"ad_group_criterion.criterion_id" => format!("{}", self.ad_group_criterion.as_ref().unwrap().criterion_id),
"ad_group_criterion.status" => format!("{}", self.ad_group_criterion.as_ref().unwrap().status()),
<snip>
}
}
- cargo test may fail due to compilation errors with example code in comment blocks of proto files. enclose them in ignore blocks.
// A message representing the message types used by a long-running operation.
// ```ignore
// Example:
//
// rpc Export(ExportRequest) returns (google.longrunning.Operation) {
// option (google.longrunning.operation_info) = {
// response_type: "ExportResponse"
// metadata_type: "ExportMetadata"
// };
// }
// ```
Documentation
- to generate docs quicker, exclude dependent crates
$$ cargo doc --no-deps --open
Credits
- Originally forked from gkkachi's gapi-grpc-rs, which used Python to generate
protos.rs - Dropped Python and migrated to custom build.rs per aquarhead