diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml
index abac03b8a..1d7a005fe 100644
--- a/.generator/schemas/v2/openapi.yaml
+++ b/.generator/schemas/v2/openapi.yaml
@@ -41237,6 +41237,114 @@ components:
type: string
x-enum-varnames:
- PROCESS
+ ProductAnalyticsServerSideEventError:
+ description: Error details.
+ properties:
+ detail:
+ description: Error message.
+ example: Malformed payload
+ type: string
+ status:
+ description: Error code.
+ example: '400'
+ type: string
+ title:
+ description: Error title.
+ example: Bad Request
+ type: string
+ type: object
+ ProductAnalyticsServerSideEventErrors:
+ description: Error response.
+ properties:
+ errors:
+ description: Structured errors.
+ items:
+ $ref: '#/components/schemas/ProductAnalyticsServerSideEventError'
+ type: array
+ type: object
+ ProductAnalyticsServerSideEventItem:
+ description: A Product Analytics server-side event.
+ properties:
+ account:
+ $ref: '#/components/schemas/ProductAnalyticsServerSideEventItemAccount'
+ application:
+ $ref: '#/components/schemas/ProductAnalyticsServerSideEventItemApplication'
+ event:
+ $ref: '#/components/schemas/ProductAnalyticsServerSideEventItemEvent'
+ session:
+ $ref: '#/components/schemas/ProductAnalyticsServerSideEventItemSession'
+ type:
+ $ref: '#/components/schemas/ProductAnalyticsServerSideEventItemType'
+ usr:
+ $ref: '#/components/schemas/ProductAnalyticsServerSideEventItemUsr'
+ required:
+ - application
+ - event
+ - type
+ type: object
+ ProductAnalyticsServerSideEventItemAccount:
+ description: The account linked to your event.
+ properties:
+ id:
+ description: The account ID used in Datadog.
+ example: account-67890
+ type: string
+ required:
+ - id
+ type: object
+ ProductAnalyticsServerSideEventItemApplication:
+ description: The application in which you want to send your events.
+ properties:
+ id:
+ description: 'The application ID of your application. It can be found in
+ your
+
+ [application management page](https://app.datadoghq.com/rum/list).'
+ example: 123abcde-123a-123b-1234-123456789abc
+ type: string
+ required:
+ - id
+ type: object
+ ProductAnalyticsServerSideEventItemEvent:
+ description: Fields used for the event.
+ properties:
+ name:
+ description: The name of your event, which is used for search in the same
+ way as view or action names.
+ example: payment.processed
+ type: string
+ required:
+ - name
+ type: object
+ ProductAnalyticsServerSideEventItemSession:
+ description: The session linked to your event.
+ properties:
+ id:
+ description: The session ID captured by the SDK.
+ example: session-abcdef
+ type: string
+ required:
+ - id
+ type: object
+ ProductAnalyticsServerSideEventItemType:
+ description: The type of Product Analytics event. Must be `server` for server-side
+ events.
+ enum:
+ - server
+ example: server
+ type: string
+ x-enum-varnames:
+ - SERVER
+ ProductAnalyticsServerSideEventItemUsr:
+ description: The user linked to your event.
+ properties:
+ id:
+ description: The user ID used in Datadog.
+ example: user-12345
+ type: string
+ required:
+ - id
+ type: object
Project:
description: A Project
properties:
@@ -78009,6 +78117,218 @@ paths:
x-permission:
operator: OPEN
permissions: []
+ /api/v2/prodlytics:
+ post:
+ description: 'Send server-side events to Product Analytics. Server-side events
+ are retained for 15 months.
+
+
+ Server-Side events in Product Analytics are helpful for tracking events that
+ occur on the server,
+
+ as opposed to client-side events, which are captured by Real User Monitoring
+ (RUM) SDKs.
+
+ This allows for a more comprehensive view of the user journey by including
+ actions that happen on the server.
+
+ Typical examples could be `checkout.completed` or `payment.processed`.
+
+
+ Ingested server-side events are integrated into Product Analytics to allow
+ users to select and filter
+
+ these events in the event picker, similar to how views or actions are handled.
+
+
+ **Requirements:**
+
+ - At least one of `usr`, `account`, or `session` must be provided with a valid
+ ID.
+
+ - The `application.id` must reference a Product Analytics-enabled application.
+
+
+ **Custom Attributes:**
+
+ Any additional fields in the payload are flattened and searchable as facets.
+
+ For example, a payload with `{"customer": {"tier": "premium"}}` is searchable
+ with
+
+ the syntax `@customer.tier:premium` in Datadog.
+
+
+ The status codes answered by the HTTP API are:
+
+ - 202: Accepted: The request has been accepted for processing
+
+ - 400: Bad request (likely an issue in the payload formatting)
+
+ - 401: Unauthorized (likely a missing API Key)
+
+ - 403: Permission issue (likely using an invalid API Key)
+
+ - 408: Request Timeout, request should be retried after some time
+
+ - 413: Payload too large (batch is above 5MB uncompressed)
+
+ - 429: Too Many Requests, request should be retried after some time
+
+ - 500: Internal Server Error, the server encountered an unexpected condition
+ that prevented it from fulfilling the request, request should be retried after
+ some time
+
+ - 503: Service Unavailable, the server is not ready to handle the request
+ probably because it is overloaded, request should be retried after some time'
+ operationId: SubmitProductAnalyticsEvent
+ requestBody:
+ content:
+ application/json:
+ examples:
+ event-with-account:
+ description: Send a server-side event linked to an account.
+ summary: Event with account ID
+ value:
+ account:
+ id: account-456
+ application:
+ id: 123abcde-123a-123b-1234-123456789abc
+ event:
+ name: checkout.completed
+ type: server
+ event-with-custom-attributes:
+ description: Send a server-side event with additional custom attributes.
+ summary: Event with custom attributes
+ value:
+ application:
+ id: 123abcde-123a-123b-1234-123456789abc
+ customer:
+ tier: premium
+ event:
+ name: payment.processed
+ type: server
+ usr:
+ id: '123'
+ event-with-session:
+ description: Send a server-side event linked to a session.
+ summary: Event with session ID
+ value:
+ application:
+ id: 123abcde-123a-123b-1234-123456789abc
+ event:
+ name: form.submitted
+ session:
+ id: session-789
+ type: server
+ simple-event-with-user:
+ description: Send a server-side event linked to a user.
+ summary: Simple event with user ID
+ value:
+ application:
+ id: 123abcde-123a-123b-1234-123456789abc
+ event:
+ name: payment.processed
+ type: server
+ usr:
+ id: '123'
+ schema:
+ $ref: '#/components/schemas/ProductAnalyticsServerSideEventItem'
+ description: Server-side event to send (JSON format).
+ required: true
+ responses:
+ '202':
+ content:
+ application/json:
+ schema:
+ type: object
+ description: Request accepted for processing (always 202 empty JSON).
+ '400':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProductAnalyticsServerSideEventErrors'
+ description: Bad Request
+ '401':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProductAnalyticsServerSideEventErrors'
+ description: Unauthorized
+ '403':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProductAnalyticsServerSideEventErrors'
+ description: Forbidden
+ '408':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProductAnalyticsServerSideEventErrors'
+ description: Request Timeout
+ '413':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProductAnalyticsServerSideEventErrors'
+ description: Payload Too Large
+ '429':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProductAnalyticsServerSideEventErrors'
+ description: Too Many Requests
+ '500':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProductAnalyticsServerSideEventErrors'
+ description: Internal Server Error
+ '503':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProductAnalyticsServerSideEventErrors'
+ description: Service Unavailable
+ security:
+ - apiKeyAuth: []
+ servers:
+ - url: https://{subdomain}.{site}
+ variables:
+ site:
+ default: datadoghq.com
+ description: The regional site for customers.
+ enum:
+ - datadoghq.com
+ - us3.datadoghq.com
+ - us5.datadoghq.com
+ - ap1.datadoghq.com
+ - ap2.datadoghq.com
+ - datadoghq.eu
+ subdomain:
+ default: browser-intake
+ description: The subdomain where the API is deployed.
+ - url: '{protocol}://{name}'
+ variables:
+ name:
+ default: browser-intake-datadoghq.com
+ description: Full site DNS name.
+ protocol:
+ default: https
+ description: The protocol for accessing the API.
+ - url: https://{subdomain}.{site}
+ variables:
+ site:
+ default: datadoghq.com
+ description: Any Datadog deployment.
+ subdomain:
+ default: browser-intake
+ description: The subdomain where the API is deployed.
+ summary: Send server-side events
+ tags:
+ - Product Analytics
+ x-codegen-request-body-name: body
/api/v2/product-analytics/accounts/facet_info:
post:
description: Get facet information for account attributes including possible
@@ -90205,6 +90525,18 @@ tags:
See the [Live Processes page](https://docs.datadoghq.com/infrastructure/process/)
for more information.
name: Processes
+- description: 'Send server-side events to Product Analytics. Server-Side Events Ingestion
+ allows you to collect custom events
+
+ from any server-side source, and retains events for 15 months. Server-side events
+ are helpful for understanding
+
+ causes of a funnel drop-off which are external to the client-side (for example,
+ payment processing error).
+
+ See the [Product Analytics page](https://docs.datadoghq.com/product_analytics/)
+ for more information.'
+ name: Product Analytics
- description: Manage your Real User Monitoring (RUM) applications, and search or
aggregate your RUM events over HTTP. See the [RUM & Session Replay page](https://docs.datadoghq.com/real_user_monitoring/)
for more information
diff --git a/examples/v2_product-analytics_SubmitProductAnalyticsEvent.rs b/examples/v2_product-analytics_SubmitProductAnalyticsEvent.rs
new file mode 100644
index 000000000..0727d7182
--- /dev/null
+++ b/examples/v2_product-analytics_SubmitProductAnalyticsEvent.rs
@@ -0,0 +1,39 @@
+// Send server-side events returns "Request accepted for processing (always 202
+// empty JSON)." response
+use datadog_api_client::datadog;
+use datadog_api_client::datadogV2::api_product_analytics::ProductAnalyticsAPI;
+use datadog_api_client::datadogV2::model::ProductAnalyticsServerSideEventItem;
+use datadog_api_client::datadogV2::model::ProductAnalyticsServerSideEventItemAccount;
+use datadog_api_client::datadogV2::model::ProductAnalyticsServerSideEventItemApplication;
+use datadog_api_client::datadogV2::model::ProductAnalyticsServerSideEventItemEvent;
+use datadog_api_client::datadogV2::model::ProductAnalyticsServerSideEventItemSession;
+use datadog_api_client::datadogV2::model::ProductAnalyticsServerSideEventItemType;
+use datadog_api_client::datadogV2::model::ProductAnalyticsServerSideEventItemUsr;
+
+#[tokio::main]
+async fn main() {
+ let body = ProductAnalyticsServerSideEventItem::new(
+ ProductAnalyticsServerSideEventItemApplication::new(
+ "123abcde-123a-123b-1234-123456789abc".to_string(),
+ ),
+ ProductAnalyticsServerSideEventItemEvent::new("payment.processed".to_string()),
+ ProductAnalyticsServerSideEventItemType::SERVER,
+ )
+ .account(ProductAnalyticsServerSideEventItemAccount::new(
+ "account-67890".to_string(),
+ ))
+ .session(ProductAnalyticsServerSideEventItemSession::new(
+ "session-abcdef".to_string(),
+ ))
+ .usr(ProductAnalyticsServerSideEventItemUsr::new(
+ "user-12345".to_string(),
+ ));
+ let configuration = datadog::Configuration::new();
+ let api = ProductAnalyticsAPI::with_config(configuration);
+ let resp = api.submit_product_analytics_event(body).await;
+ if let Ok(value) = resp {
+ println!("{:#?}", value);
+ } else {
+ println!("{:#?}", resp.unwrap_err());
+ }
+}
diff --git a/src/datadog/configuration.rs b/src/datadog/configuration.rs
index 2eab236e9..170f5d430 100644
--- a/src/datadog/configuration.rs
+++ b/src/datadog/configuration.rs
@@ -988,6 +988,84 @@ lazy_static! {
},
],
),
+ (
+ "v2.submit_product_analytics_event".into(),
+ vec![
+ ServerConfiguration {
+ url: "https://{subdomain}.{site}".into(),
+ description: "No description provided".into(),
+ variables: HashMap::from([
+ (
+ "site".into(),
+ ServerVariable {
+ description: "The regional site for customers.".into(),
+ default_value: "datadoghq.com".into(),
+ enum_values: vec![
+ "datadoghq.com".into(),
+ "us3.datadoghq.com".into(),
+ "us5.datadoghq.com".into(),
+ "ap1.datadoghq.com".into(),
+ "ap2.datadoghq.com".into(),
+ "datadoghq.eu".into(),
+ ],
+ },
+ ),
+ (
+ "subdomain".into(),
+ ServerVariable {
+ description: "The subdomain where the API is deployed.".into(),
+ default_value: "browser-intake".into(),
+ enum_values: vec![],
+ },
+ ),
+ ]),
+ },
+ ServerConfiguration {
+ url: "{protocol}://{name}".into(),
+ description: "No description provided".into(),
+ variables: HashMap::from([
+ (
+ "name".into(),
+ ServerVariable {
+ description: "Full site DNS name.".into(),
+ default_value: "browser-intake-datadoghq.com".into(),
+ enum_values: vec![],
+ },
+ ),
+ (
+ "protocol".into(),
+ ServerVariable {
+ description: "The protocol for accessing the API.".into(),
+ default_value: "https".into(),
+ enum_values: vec![],
+ },
+ ),
+ ]),
+ },
+ ServerConfiguration {
+ url: "https://{subdomain}.{site}".into(),
+ description: "No description provided".into(),
+ variables: HashMap::from([
+ (
+ "site".into(),
+ ServerVariable {
+ description: "Any Datadog deployment.".into(),
+ default_value: "datadoghq.com".into(),
+ enum_values: vec![],
+ },
+ ),
+ (
+ "subdomain".into(),
+ ServerVariable {
+ description: "The subdomain where the API is deployed.".into(),
+ default_value: "browser-intake".into(),
+ enum_values: vec![],
+ },
+ ),
+ ]),
+ },
+ ],
+ ),
])
};
}
diff --git a/src/datadogV2/api/api_product_analytics.rs b/src/datadogV2/api/api_product_analytics.rs
new file mode 100644
index 000000000..e125eb06b
--- /dev/null
+++ b/src/datadogV2/api/api_product_analytics.rs
@@ -0,0 +1,296 @@
+// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License.
+// This product includes software developed at Datadog (https://www.datadoghq.com/).
+// Copyright 2019-Present Datadog, Inc.
+use crate::datadog;
+use flate2::{
+ write::{GzEncoder, ZlibEncoder},
+ Compression,
+};
+use reqwest::header::{HeaderMap, HeaderValue};
+use serde::{Deserialize, Serialize};
+use std::io::Write;
+
+/// SubmitProductAnalyticsEventError is a struct for typed errors of method [`ProductAnalyticsAPI::submit_product_analytics_event`]
+#[derive(Debug, Clone, Serialize, Deserialize)]
+#[serde(untagged)]
+pub enum SubmitProductAnalyticsEventError {
+ ProductAnalyticsServerSideEventErrors(
+ crate::datadogV2::model::ProductAnalyticsServerSideEventErrors,
+ ),
+ UnknownValue(serde_json::Value),
+}
+
+/// Send server-side events to Product Analytics. Server-Side Events Ingestion allows you to collect custom events
+/// from any server-side source, and retains events for 15 months. Server-side events are helpful for understanding
+/// causes of a funnel drop-off which are external to the client-side (for example, payment processing error).
+/// See the [Product Analytics page]() for more information.
+#[derive(Debug, Clone)]
+pub struct ProductAnalyticsAPI {
+ config: datadog::Configuration,
+ client: reqwest_middleware::ClientWithMiddleware,
+}
+
+impl Default for ProductAnalyticsAPI {
+ fn default() -> Self {
+ Self::with_config(datadog::Configuration::default())
+ }
+}
+
+impl ProductAnalyticsAPI {
+ pub fn new() -> Self {
+ Self::default()
+ }
+ pub fn with_config(config: datadog::Configuration) -> Self {
+ let mut reqwest_client_builder = reqwest::Client::builder();
+
+ if let Some(proxy_url) = &config.proxy_url {
+ let proxy = reqwest::Proxy::all(proxy_url).expect("Failed to parse proxy URL");
+ reqwest_client_builder = reqwest_client_builder.proxy(proxy);
+ }
+
+ let mut middleware_client_builder =
+ reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap());
+
+ if config.enable_retry {
+ struct RetryableStatus;
+ impl reqwest_retry::RetryableStrategy for RetryableStatus {
+ fn handle(
+ &self,
+ res: &Result,
+ ) -> Option {
+ match res {
+ Ok(success) => reqwest_retry::default_on_request_success(success),
+ Err(_) => None,
+ }
+ }
+ }
+ let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder()
+ .build_with_max_retries(config.max_retries);
+
+ let retry_middleware =
+ reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy(
+ backoff_policy,
+ RetryableStatus,
+ );
+
+ middleware_client_builder = middleware_client_builder.with(retry_middleware);
+ }
+
+ let client = middleware_client_builder.build();
+
+ Self { config, client }
+ }
+
+ pub fn with_client_and_config(
+ config: datadog::Configuration,
+ client: reqwest_middleware::ClientWithMiddleware,
+ ) -> Self {
+ Self { config, client }
+ }
+
+ /// Send server-side events to Product Analytics. Server-side events are retained for 15 months.
+ ///
+ /// Server-Side events in Product Analytics are helpful for tracking events that occur on the server,
+ /// as opposed to client-side events, which are captured by Real User Monitoring (RUM) SDKs.
+ /// This allows for a more comprehensive view of the user journey by including actions that happen on the server.
+ /// Typical examples could be `checkout.completed` or `payment.processed`.
+ ///
+ /// Ingested server-side events are integrated into Product Analytics to allow users to select and filter
+ /// these events in the event picker, similar to how views or actions are handled.
+ ///
+ /// **Requirements:**
+ /// - At least one of `usr`, `account`, or `session` must be provided with a valid ID.
+ /// - The `application.id` must reference a Product Analytics-enabled application.
+ ///
+ /// **Custom Attributes:**
+ /// Any additional fields in the payload are flattened and searchable as facets.
+ /// For example, a payload with `{"customer": {"tier": "premium"}}` is searchable with
+ /// the syntax `@customer.tier:premium` in Datadog.
+ ///
+ /// The status codes answered by the HTTP API are:
+ /// - 202: Accepted: The request has been accepted for processing
+ /// - 400: Bad request (likely an issue in the payload formatting)
+ /// - 401: Unauthorized (likely a missing API Key)
+ /// - 403: Permission issue (likely using an invalid API Key)
+ /// - 408: Request Timeout, request should be retried after some time
+ /// - 413: Payload too large (batch is above 5MB uncompressed)
+ /// - 429: Too Many Requests, request should be retried after some time
+ /// - 500: Internal Server Error, the server encountered an unexpected condition that prevented it from fulfilling the request, request should be retried after some time
+ /// - 503: Service Unavailable, the server is not ready to handle the request probably because it is overloaded, request should be retried after some time
+ pub async fn submit_product_analytics_event(
+ &self,
+ body: crate::datadogV2::model::ProductAnalyticsServerSideEventItem,
+ ) -> Result<
+ std::collections::BTreeMap,
+ datadog::Error,
+ > {
+ match self
+ .submit_product_analytics_event_with_http_info(body)
+ .await
+ {
+ Ok(response_content) => {
+ if let Some(e) = response_content.entity {
+ Ok(e)
+ } else {
+ Err(datadog::Error::Serde(serde::de::Error::custom(
+ "response content was None",
+ )))
+ }
+ }
+ Err(err) => Err(err),
+ }
+ }
+
+ /// Send server-side events to Product Analytics. Server-side events are retained for 15 months.
+ ///
+ /// Server-Side events in Product Analytics are helpful for tracking events that occur on the server,
+ /// as opposed to client-side events, which are captured by Real User Monitoring (RUM) SDKs.
+ /// This allows for a more comprehensive view of the user journey by including actions that happen on the server.
+ /// Typical examples could be `checkout.completed` or `payment.processed`.
+ ///
+ /// Ingested server-side events are integrated into Product Analytics to allow users to select and filter
+ /// these events in the event picker, similar to how views or actions are handled.
+ ///
+ /// **Requirements:**
+ /// - At least one of `usr`, `account`, or `session` must be provided with a valid ID.
+ /// - The `application.id` must reference a Product Analytics-enabled application.
+ ///
+ /// **Custom Attributes:**
+ /// Any additional fields in the payload are flattened and searchable as facets.
+ /// For example, a payload with `{"customer": {"tier": "premium"}}` is searchable with
+ /// the syntax `@customer.tier:premium` in Datadog.
+ ///
+ /// The status codes answered by the HTTP API are:
+ /// - 202: Accepted: The request has been accepted for processing
+ /// - 400: Bad request (likely an issue in the payload formatting)
+ /// - 401: Unauthorized (likely a missing API Key)
+ /// - 403: Permission issue (likely using an invalid API Key)
+ /// - 408: Request Timeout, request should be retried after some time
+ /// - 413: Payload too large (batch is above 5MB uncompressed)
+ /// - 429: Too Many Requests, request should be retried after some time
+ /// - 500: Internal Server Error, the server encountered an unexpected condition that prevented it from fulfilling the request, request should be retried after some time
+ /// - 503: Service Unavailable, the server is not ready to handle the request probably because it is overloaded, request should be retried after some time
+ pub async fn submit_product_analytics_event_with_http_info(
+ &self,
+ body: crate::datadogV2::model::ProductAnalyticsServerSideEventItem,
+ ) -> Result<
+ datadog::ResponseContent>,
+ datadog::Error,
+ > {
+ let local_configuration = &self.config;
+ let operation_id = "v2.submit_product_analytics_event";
+
+ let local_client = &self.client;
+
+ let local_uri_str = format!(
+ "{}/api/v2/prodlytics",
+ local_configuration.get_operation_host(operation_id)
+ );
+ let mut local_req_builder =
+ local_client.request(reqwest::Method::POST, local_uri_str.as_str());
+
+ // build headers
+ let mut headers = HeaderMap::new();
+ headers.insert("Content-Type", HeaderValue::from_static("application/json"));
+ headers.insert("Accept", HeaderValue::from_static("application/json"));
+
+ // build user agent
+ match HeaderValue::from_str(local_configuration.user_agent.as_str()) {
+ Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent),
+ Err(e) => {
+ log::warn!("Failed to parse user agent header: {e}, falling back to default");
+ headers.insert(
+ reqwest::header::USER_AGENT,
+ HeaderValue::from_static(datadog::DEFAULT_USER_AGENT.as_str()),
+ )
+ }
+ };
+
+ // build auth
+ if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") {
+ headers.insert(
+ "DD-API-KEY",
+ HeaderValue::from_str(local_key.key.as_str())
+ .expect("failed to parse DD-API-KEY header"),
+ );
+ };
+
+ // build body parameters
+ let output = Vec::new();
+ let mut ser = serde_json::Serializer::with_formatter(output, datadog::DDFormatter);
+ if body.serialize(&mut ser).is_ok() {
+ if let Some(content_encoding) = headers.get("Content-Encoding") {
+ match content_encoding.to_str().unwrap_or_default() {
+ "gzip" => {
+ let mut enc = GzEncoder::new(Vec::new(), Compression::default());
+ let _ = enc.write_all(ser.into_inner().as_slice());
+ match enc.finish() {
+ Ok(buf) => {
+ local_req_builder = local_req_builder.body(buf);
+ }
+ Err(e) => return Err(datadog::Error::Io(e)),
+ }
+ }
+ "deflate" => {
+ let mut enc = ZlibEncoder::new(Vec::new(), Compression::default());
+ let _ = enc.write_all(ser.into_inner().as_slice());
+ match enc.finish() {
+ Ok(buf) => {
+ local_req_builder = local_req_builder.body(buf);
+ }
+ Err(e) => return Err(datadog::Error::Io(e)),
+ }
+ }
+ "zstd1" => {
+ let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap();
+ let _ = enc.write_all(ser.into_inner().as_slice());
+ match enc.finish() {
+ Ok(buf) => {
+ local_req_builder = local_req_builder.body(buf);
+ }
+ Err(e) => return Err(datadog::Error::Io(e)),
+ }
+ }
+ _ => {
+ local_req_builder = local_req_builder.body(ser.into_inner());
+ }
+ }
+ } else {
+ local_req_builder = local_req_builder.body(ser.into_inner());
+ }
+ }
+
+ local_req_builder = local_req_builder.headers(headers);
+ let local_req = local_req_builder.build()?;
+ log::debug!("request content: {:?}", local_req.body());
+ let local_resp = local_client.execute(local_req).await?;
+
+ let local_status = local_resp.status();
+ let local_content = local_resp.text().await?;
+ log::debug!("response content: {}", local_content);
+
+ if !local_status.is_client_error() && !local_status.is_server_error() {
+ match serde_json::from_str::>(
+ &local_content,
+ ) {
+ Ok(e) => {
+ return Ok(datadog::ResponseContent {
+ status: local_status,
+ content: local_content,
+ entity: Some(e),
+ })
+ }
+ Err(e) => return Err(datadog::Error::Serde(e)),
+ };
+ } else {
+ let local_entity: Option =
+ serde_json::from_str(&local_content).ok();
+ let local_error = datadog::ResponseContent {
+ status: local_status,
+ content: local_content,
+ entity: local_entity,
+ };
+ Err(datadog::Error::ResponseError(local_error))
+ }
+ }
+}
diff --git a/src/datadogV2/api/mod.rs b/src/datadogV2/api/mod.rs
index 4d3e9cb7e..1c89b3b0b 100644
--- a/src/datadogV2/api/mod.rs
+++ b/src/datadogV2/api/mod.rs
@@ -63,6 +63,7 @@ pub mod api_org_connections;
pub mod api_organizations;
pub mod api_powerpack;
pub mod api_processes;
+pub mod api_product_analytics;
pub mod api_reference_tables;
pub mod api_restriction_policies;
pub mod api_roles;
diff --git a/src/datadogV2/mod.rs b/src/datadogV2/mod.rs
index 3d7767d4f..2ee0a112a 100644
--- a/src/datadogV2/mod.rs
+++ b/src/datadogV2/mod.rs
@@ -64,6 +64,7 @@ pub use self::api::api_org_connections;
pub use self::api::api_organizations;
pub use self::api::api_powerpack;
pub use self::api::api_processes;
+pub use self::api::api_product_analytics;
pub use self::api::api_reference_tables;
pub use self::api::api_restriction_policies;
pub use self::api::api_roles;
diff --git a/src/datadogV2/model/mod.rs b/src/datadogV2/model/mod.rs
index 670570ff9..10d3adf90 100644
--- a/src/datadogV2/model/mod.rs
+++ b/src/datadogV2/model/mod.rs
@@ -4560,6 +4560,24 @@ pub mod model_process_summaries_meta;
pub use self::model_process_summaries_meta::ProcessSummariesMeta;
pub mod model_process_summaries_meta_page;
pub use self::model_process_summaries_meta_page::ProcessSummariesMetaPage;
+pub mod model_product_analytics_server_side_event_item;
+pub use self::model_product_analytics_server_side_event_item::ProductAnalyticsServerSideEventItem;
+pub mod model_product_analytics_server_side_event_item_account;
+pub use self::model_product_analytics_server_side_event_item_account::ProductAnalyticsServerSideEventItemAccount;
+pub mod model_product_analytics_server_side_event_item_application;
+pub use self::model_product_analytics_server_side_event_item_application::ProductAnalyticsServerSideEventItemApplication;
+pub mod model_product_analytics_server_side_event_item_event;
+pub use self::model_product_analytics_server_side_event_item_event::ProductAnalyticsServerSideEventItemEvent;
+pub mod model_product_analytics_server_side_event_item_session;
+pub use self::model_product_analytics_server_side_event_item_session::ProductAnalyticsServerSideEventItemSession;
+pub mod model_product_analytics_server_side_event_item_type;
+pub use self::model_product_analytics_server_side_event_item_type::ProductAnalyticsServerSideEventItemType;
+pub mod model_product_analytics_server_side_event_item_usr;
+pub use self::model_product_analytics_server_side_event_item_usr::ProductAnalyticsServerSideEventItemUsr;
+pub mod model_product_analytics_server_side_event_errors;
+pub use self::model_product_analytics_server_side_event_errors::ProductAnalyticsServerSideEventErrors;
+pub mod model_product_analytics_server_side_event_error;
+pub use self::model_product_analytics_server_side_event_error::ProductAnalyticsServerSideEventError;
pub mod model_facet_info_request;
pub use self::model_facet_info_request::FacetInfoRequest;
pub mod model_facet_info_request_data;
diff --git a/src/datadogV2/model/model_product_analytics_server_side_event_error.rs b/src/datadogV2/model/model_product_analytics_server_side_event_error.rs
new file mode 100644
index 000000000..f061f3561
--- /dev/null
+++ b/src/datadogV2/model/model_product_analytics_server_side_event_error.rs
@@ -0,0 +1,139 @@
+// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License.
+// This product includes software developed at Datadog (https://www.datadoghq.com/).
+// Copyright 2019-Present Datadog, Inc.
+use serde::de::{Error, MapAccess, Visitor};
+use serde::{Deserialize, Deserializer, Serialize};
+use serde_with::skip_serializing_none;
+use std::fmt::{self, Formatter};
+
+/// Error details.
+#[non_exhaustive]
+#[skip_serializing_none]
+#[derive(Clone, Debug, PartialEq, Serialize)]
+pub struct ProductAnalyticsServerSideEventError {
+ /// Error message.
+ #[serde(rename = "detail")]
+ pub detail: Option,
+ /// Error code.
+ #[serde(rename = "status")]
+ pub status: Option,
+ /// Error title.
+ #[serde(rename = "title")]
+ pub title: Option,
+ #[serde(flatten)]
+ pub additional_properties: std::collections::BTreeMap,
+ #[serde(skip)]
+ #[serde(default)]
+ pub(crate) _unparsed: bool,
+}
+
+impl ProductAnalyticsServerSideEventError {
+ pub fn new() -> ProductAnalyticsServerSideEventError {
+ ProductAnalyticsServerSideEventError {
+ detail: None,
+ status: None,
+ title: None,
+ additional_properties: std::collections::BTreeMap::new(),
+ _unparsed: false,
+ }
+ }
+
+ pub fn detail(mut self, value: String) -> Self {
+ self.detail = Some(value);
+ self
+ }
+
+ pub fn status(mut self, value: String) -> Self {
+ self.status = Some(value);
+ self
+ }
+
+ pub fn title(mut self, value: String) -> Self {
+ self.title = Some(value);
+ self
+ }
+
+ pub fn additional_properties(
+ mut self,
+ value: std::collections::BTreeMap,
+ ) -> Self {
+ self.additional_properties = value;
+ self
+ }
+}
+
+impl Default for ProductAnalyticsServerSideEventError {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl<'de> Deserialize<'de> for ProductAnalyticsServerSideEventError {
+ fn deserialize(deserializer: D) -> Result
+ where
+ D: Deserializer<'de>,
+ {
+ struct ProductAnalyticsServerSideEventErrorVisitor;
+ impl<'a> Visitor<'a> for ProductAnalyticsServerSideEventErrorVisitor {
+ type Value = ProductAnalyticsServerSideEventError;
+
+ fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ f.write_str("a mapping")
+ }
+
+ fn visit_map(self, mut map: M) -> Result
+ where
+ M: MapAccess<'a>,
+ {
+ let mut detail: Option = None;
+ let mut status: Option = None;
+ let mut title: Option = None;
+ let mut additional_properties: std::collections::BTreeMap<
+ String,
+ serde_json::Value,
+ > = std::collections::BTreeMap::new();
+ let mut _unparsed = false;
+
+ while let Some((k, v)) = map.next_entry::()? {
+ match k.as_str() {
+ "detail" => {
+ if v.is_null() {
+ continue;
+ }
+ detail = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
+ }
+ "status" => {
+ if v.is_null() {
+ continue;
+ }
+ status = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
+ }
+ "title" => {
+ if v.is_null() {
+ continue;
+ }
+ title = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
+ }
+ &_ => {
+ if let Ok(value) = serde_json::from_value(v.clone()) {
+ additional_properties.insert(k, value);
+ }
+ }
+ }
+ }
+
+ let content = ProductAnalyticsServerSideEventError {
+ detail,
+ status,
+ title,
+ additional_properties,
+ _unparsed,
+ };
+
+ Ok(content)
+ }
+ }
+
+ deserializer.deserialize_any(ProductAnalyticsServerSideEventErrorVisitor)
+ }
+}
diff --git a/src/datadogV2/model/model_product_analytics_server_side_event_errors.rs b/src/datadogV2/model/model_product_analytics_server_side_event_errors.rs
new file mode 100644
index 000000000..0326913e3
--- /dev/null
+++ b/src/datadogV2/model/model_product_analytics_server_side_event_errors.rs
@@ -0,0 +1,110 @@
+// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License.
+// This product includes software developed at Datadog (https://www.datadoghq.com/).
+// Copyright 2019-Present Datadog, Inc.
+use serde::de::{Error, MapAccess, Visitor};
+use serde::{Deserialize, Deserializer, Serialize};
+use serde_with::skip_serializing_none;
+use std::fmt::{self, Formatter};
+
+/// Error response.
+#[non_exhaustive]
+#[skip_serializing_none]
+#[derive(Clone, Debug, PartialEq, Serialize)]
+pub struct ProductAnalyticsServerSideEventErrors {
+ /// Structured errors.
+ #[serde(rename = "errors")]
+ pub errors: Option>,
+ #[serde(flatten)]
+ pub additional_properties: std::collections::BTreeMap,
+ #[serde(skip)]
+ #[serde(default)]
+ pub(crate) _unparsed: bool,
+}
+
+impl ProductAnalyticsServerSideEventErrors {
+ pub fn new() -> ProductAnalyticsServerSideEventErrors {
+ ProductAnalyticsServerSideEventErrors {
+ errors: None,
+ additional_properties: std::collections::BTreeMap::new(),
+ _unparsed: false,
+ }
+ }
+
+ pub fn errors(
+ mut self,
+ value: Vec,
+ ) -> Self {
+ self.errors = Some(value);
+ self
+ }
+
+ pub fn additional_properties(
+ mut self,
+ value: std::collections::BTreeMap,
+ ) -> Self {
+ self.additional_properties = value;
+ self
+ }
+}
+
+impl Default for ProductAnalyticsServerSideEventErrors {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl<'de> Deserialize<'de> for ProductAnalyticsServerSideEventErrors {
+ fn deserialize(deserializer: D) -> Result
+ where
+ D: Deserializer<'de>,
+ {
+ struct ProductAnalyticsServerSideEventErrorsVisitor;
+ impl<'a> Visitor<'a> for ProductAnalyticsServerSideEventErrorsVisitor {
+ type Value = ProductAnalyticsServerSideEventErrors;
+
+ fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ f.write_str("a mapping")
+ }
+
+ fn visit_map(self, mut map: M) -> Result
+ where
+ M: MapAccess<'a>,
+ {
+ let mut errors: Option<
+ Vec,
+ > = None;
+ let mut additional_properties: std::collections::BTreeMap<
+ String,
+ serde_json::Value,
+ > = std::collections::BTreeMap::new();
+ let mut _unparsed = false;
+
+ while let Some((k, v)) = map.next_entry::()? {
+ match k.as_str() {
+ "errors" => {
+ if v.is_null() {
+ continue;
+ }
+ errors = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
+ }
+ &_ => {
+ if let Ok(value) = serde_json::from_value(v.clone()) {
+ additional_properties.insert(k, value);
+ }
+ }
+ }
+ }
+
+ let content = ProductAnalyticsServerSideEventErrors {
+ errors,
+ additional_properties,
+ _unparsed,
+ };
+
+ Ok(content)
+ }
+ }
+
+ deserializer.deserialize_any(ProductAnalyticsServerSideEventErrorsVisitor)
+ }
+}
diff --git a/src/datadogV2/model/model_product_analytics_server_side_event_item.rs b/src/datadogV2/model/model_product_analytics_server_side_event_item.rs
new file mode 100644
index 000000000..353e668ed
--- /dev/null
+++ b/src/datadogV2/model/model_product_analytics_server_side_event_item.rs
@@ -0,0 +1,198 @@
+// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License.
+// This product includes software developed at Datadog (https://www.datadoghq.com/).
+// Copyright 2019-Present Datadog, Inc.
+use serde::de::{Error, MapAccess, Visitor};
+use serde::{Deserialize, Deserializer, Serialize};
+use serde_with::skip_serializing_none;
+use std::fmt::{self, Formatter};
+
+/// A Product Analytics server-side event.
+#[non_exhaustive]
+#[skip_serializing_none]
+#[derive(Clone, Debug, PartialEq, Serialize)]
+pub struct ProductAnalyticsServerSideEventItem {
+ /// The account linked to your event.
+ #[serde(rename = "account")]
+ pub account: Option,
+ /// The application in which you want to send your events.
+ #[serde(rename = "application")]
+ pub application: crate::datadogV2::model::ProductAnalyticsServerSideEventItemApplication,
+ /// Fields used for the event.
+ #[serde(rename = "event")]
+ pub event: crate::datadogV2::model::ProductAnalyticsServerSideEventItemEvent,
+ /// The session linked to your event.
+ #[serde(rename = "session")]
+ pub session: Option,
+ /// The type of Product Analytics event. Must be `server` for server-side events.
+ #[serde(rename = "type")]
+ pub type_: crate::datadogV2::model::ProductAnalyticsServerSideEventItemType,
+ /// The user linked to your event.
+ #[serde(rename = "usr")]
+ pub usr: Option,
+ #[serde(flatten)]
+ pub additional_properties: std::collections::BTreeMap,
+ #[serde(skip)]
+ #[serde(default)]
+ pub(crate) _unparsed: bool,
+}
+
+impl ProductAnalyticsServerSideEventItem {
+ pub fn new(
+ application: crate::datadogV2::model::ProductAnalyticsServerSideEventItemApplication,
+ event: crate::datadogV2::model::ProductAnalyticsServerSideEventItemEvent,
+ type_: crate::datadogV2::model::ProductAnalyticsServerSideEventItemType,
+ ) -> ProductAnalyticsServerSideEventItem {
+ ProductAnalyticsServerSideEventItem {
+ account: None,
+ application,
+ event,
+ session: None,
+ type_,
+ usr: None,
+ additional_properties: std::collections::BTreeMap::new(),
+ _unparsed: false,
+ }
+ }
+
+ pub fn account(
+ mut self,
+ value: crate::datadogV2::model::ProductAnalyticsServerSideEventItemAccount,
+ ) -> Self {
+ self.account = Some(value);
+ self
+ }
+
+ pub fn session(
+ mut self,
+ value: crate::datadogV2::model::ProductAnalyticsServerSideEventItemSession,
+ ) -> Self {
+ self.session = Some(value);
+ self
+ }
+
+ pub fn usr(
+ mut self,
+ value: crate::datadogV2::model::ProductAnalyticsServerSideEventItemUsr,
+ ) -> Self {
+ self.usr = Some(value);
+ self
+ }
+
+ pub fn additional_properties(
+ mut self,
+ value: std::collections::BTreeMap,
+ ) -> Self {
+ self.additional_properties = value;
+ self
+ }
+}
+
+impl<'de> Deserialize<'de> for ProductAnalyticsServerSideEventItem {
+ fn deserialize(deserializer: D) -> Result
+ where
+ D: Deserializer<'de>,
+ {
+ struct ProductAnalyticsServerSideEventItemVisitor;
+ impl<'a> Visitor<'a> for ProductAnalyticsServerSideEventItemVisitor {
+ type Value = ProductAnalyticsServerSideEventItem;
+
+ fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ f.write_str("a mapping")
+ }
+
+ fn visit_map(self, mut map: M) -> Result
+ where
+ M: MapAccess<'a>,
+ {
+ let mut account: Option<
+ crate::datadogV2::model::ProductAnalyticsServerSideEventItemAccount,
+ > = None;
+ let mut application: Option<
+ crate::datadogV2::model::ProductAnalyticsServerSideEventItemApplication,
+ > = None;
+ let mut event: Option<
+ crate::datadogV2::model::ProductAnalyticsServerSideEventItemEvent,
+ > = None;
+ let mut session: Option<
+ crate::datadogV2::model::ProductAnalyticsServerSideEventItemSession,
+ > = None;
+ let mut type_: Option<
+ crate::datadogV2::model::ProductAnalyticsServerSideEventItemType,
+ > = None;
+ let mut usr: Option<
+ crate::datadogV2::model::ProductAnalyticsServerSideEventItemUsr,
+ > = None;
+ let mut additional_properties: std::collections::BTreeMap<
+ String,
+ serde_json::Value,
+ > = std::collections::BTreeMap::new();
+ let mut _unparsed = false;
+
+ while let Some((k, v)) = map.next_entry::()? {
+ match k.as_str() {
+ "account" => {
+ if v.is_null() {
+ continue;
+ }
+ account = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
+ }
+ "application" => {
+ application =
+ Some(serde_json::from_value(v).map_err(M::Error::custom)?);
+ }
+ "event" => {
+ event = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
+ }
+ "session" => {
+ if v.is_null() {
+ continue;
+ }
+ session = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
+ }
+ "type" => {
+ type_ = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
+ if let Some(ref _type_) = type_ {
+ match _type_ {
+ crate::datadogV2::model::ProductAnalyticsServerSideEventItemType::UnparsedObject(_type_) => {
+ _unparsed = true;
+ },
+ _ => {}
+ }
+ }
+ }
+ "usr" => {
+ if v.is_null() {
+ continue;
+ }
+ usr = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
+ }
+ &_ => {
+ if let Ok(value) = serde_json::from_value(v.clone()) {
+ additional_properties.insert(k, value);
+ }
+ }
+ }
+ }
+ let application =
+ application.ok_or_else(|| M::Error::missing_field("application"))?;
+ let event = event.ok_or_else(|| M::Error::missing_field("event"))?;
+ let type_ = type_.ok_or_else(|| M::Error::missing_field("type_"))?;
+
+ let content = ProductAnalyticsServerSideEventItem {
+ account,
+ application,
+ event,
+ session,
+ type_,
+ usr,
+ additional_properties,
+ _unparsed,
+ };
+
+ Ok(content)
+ }
+ }
+
+ deserializer.deserialize_any(ProductAnalyticsServerSideEventItemVisitor)
+ }
+}
diff --git a/src/datadogV2/model/model_product_analytics_server_side_event_item_account.rs b/src/datadogV2/model/model_product_analytics_server_side_event_item_account.rs
new file mode 100644
index 000000000..d4f5d2497
--- /dev/null
+++ b/src/datadogV2/model/model_product_analytics_server_side_event_item_account.rs
@@ -0,0 +1,92 @@
+// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License.
+// This product includes software developed at Datadog (https://www.datadoghq.com/).
+// Copyright 2019-Present Datadog, Inc.
+use serde::de::{Error, MapAccess, Visitor};
+use serde::{Deserialize, Deserializer, Serialize};
+use serde_with::skip_serializing_none;
+use std::fmt::{self, Formatter};
+
+/// The account linked to your event.
+#[non_exhaustive]
+#[skip_serializing_none]
+#[derive(Clone, Debug, PartialEq, Serialize)]
+pub struct ProductAnalyticsServerSideEventItemAccount {
+ /// The account ID used in Datadog.
+ #[serde(rename = "id")]
+ pub id: String,
+ #[serde(flatten)]
+ pub additional_properties: std::collections::BTreeMap,
+ #[serde(skip)]
+ #[serde(default)]
+ pub(crate) _unparsed: bool,
+}
+
+impl ProductAnalyticsServerSideEventItemAccount {
+ pub fn new(id: String) -> ProductAnalyticsServerSideEventItemAccount {
+ ProductAnalyticsServerSideEventItemAccount {
+ id,
+ additional_properties: std::collections::BTreeMap::new(),
+ _unparsed: false,
+ }
+ }
+
+ pub fn additional_properties(
+ mut self,
+ value: std::collections::BTreeMap,
+ ) -> Self {
+ self.additional_properties = value;
+ self
+ }
+}
+
+impl<'de> Deserialize<'de> for ProductAnalyticsServerSideEventItemAccount {
+ fn deserialize(deserializer: D) -> Result
+ where
+ D: Deserializer<'de>,
+ {
+ struct ProductAnalyticsServerSideEventItemAccountVisitor;
+ impl<'a> Visitor<'a> for ProductAnalyticsServerSideEventItemAccountVisitor {
+ type Value = ProductAnalyticsServerSideEventItemAccount;
+
+ fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ f.write_str("a mapping")
+ }
+
+ fn visit_map(self, mut map: M) -> Result
+ where
+ M: MapAccess<'a>,
+ {
+ let mut id: Option = None;
+ let mut additional_properties: std::collections::BTreeMap<
+ String,
+ serde_json::Value,
+ > = std::collections::BTreeMap::new();
+ let mut _unparsed = false;
+
+ while let Some((k, v)) = map.next_entry::()? {
+ match k.as_str() {
+ "id" => {
+ id = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
+ }
+ &_ => {
+ if let Ok(value) = serde_json::from_value(v.clone()) {
+ additional_properties.insert(k, value);
+ }
+ }
+ }
+ }
+ let id = id.ok_or_else(|| M::Error::missing_field("id"))?;
+
+ let content = ProductAnalyticsServerSideEventItemAccount {
+ id,
+ additional_properties,
+ _unparsed,
+ };
+
+ Ok(content)
+ }
+ }
+
+ deserializer.deserialize_any(ProductAnalyticsServerSideEventItemAccountVisitor)
+ }
+}
diff --git a/src/datadogV2/model/model_product_analytics_server_side_event_item_application.rs b/src/datadogV2/model/model_product_analytics_server_side_event_item_application.rs
new file mode 100644
index 000000000..02ea21c4a
--- /dev/null
+++ b/src/datadogV2/model/model_product_analytics_server_side_event_item_application.rs
@@ -0,0 +1,93 @@
+// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License.
+// This product includes software developed at Datadog (https://www.datadoghq.com/).
+// Copyright 2019-Present Datadog, Inc.
+use serde::de::{Error, MapAccess, Visitor};
+use serde::{Deserialize, Deserializer, Serialize};
+use serde_with::skip_serializing_none;
+use std::fmt::{self, Formatter};
+
+/// The application in which you want to send your events.
+#[non_exhaustive]
+#[skip_serializing_none]
+#[derive(Clone, Debug, PartialEq, Serialize)]
+pub struct ProductAnalyticsServerSideEventItemApplication {
+ /// The application ID of your application. It can be found in your
+ /// [application management page]().
+ #[serde(rename = "id")]
+ pub id: String,
+ #[serde(flatten)]
+ pub additional_properties: std::collections::BTreeMap,
+ #[serde(skip)]
+ #[serde(default)]
+ pub(crate) _unparsed: bool,
+}
+
+impl ProductAnalyticsServerSideEventItemApplication {
+ pub fn new(id: String) -> ProductAnalyticsServerSideEventItemApplication {
+ ProductAnalyticsServerSideEventItemApplication {
+ id,
+ additional_properties: std::collections::BTreeMap::new(),
+ _unparsed: false,
+ }
+ }
+
+ pub fn additional_properties(
+ mut self,
+ value: std::collections::BTreeMap,
+ ) -> Self {
+ self.additional_properties = value;
+ self
+ }
+}
+
+impl<'de> Deserialize<'de> for ProductAnalyticsServerSideEventItemApplication {
+ fn deserialize(deserializer: D) -> Result
+ where
+ D: Deserializer<'de>,
+ {
+ struct ProductAnalyticsServerSideEventItemApplicationVisitor;
+ impl<'a> Visitor<'a> for ProductAnalyticsServerSideEventItemApplicationVisitor {
+ type Value = ProductAnalyticsServerSideEventItemApplication;
+
+ fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ f.write_str("a mapping")
+ }
+
+ fn visit_map(self, mut map: M) -> Result
+ where
+ M: MapAccess<'a>,
+ {
+ let mut id: Option = None;
+ let mut additional_properties: std::collections::BTreeMap<
+ String,
+ serde_json::Value,
+ > = std::collections::BTreeMap::new();
+ let mut _unparsed = false;
+
+ while let Some((k, v)) = map.next_entry::()? {
+ match k.as_str() {
+ "id" => {
+ id = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
+ }
+ &_ => {
+ if let Ok(value) = serde_json::from_value(v.clone()) {
+ additional_properties.insert(k, value);
+ }
+ }
+ }
+ }
+ let id = id.ok_or_else(|| M::Error::missing_field("id"))?;
+
+ let content = ProductAnalyticsServerSideEventItemApplication {
+ id,
+ additional_properties,
+ _unparsed,
+ };
+
+ Ok(content)
+ }
+ }
+
+ deserializer.deserialize_any(ProductAnalyticsServerSideEventItemApplicationVisitor)
+ }
+}
diff --git a/src/datadogV2/model/model_product_analytics_server_side_event_item_event.rs b/src/datadogV2/model/model_product_analytics_server_side_event_item_event.rs
new file mode 100644
index 000000000..d915286b8
--- /dev/null
+++ b/src/datadogV2/model/model_product_analytics_server_side_event_item_event.rs
@@ -0,0 +1,92 @@
+// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License.
+// This product includes software developed at Datadog (https://www.datadoghq.com/).
+// Copyright 2019-Present Datadog, Inc.
+use serde::de::{Error, MapAccess, Visitor};
+use serde::{Deserialize, Deserializer, Serialize};
+use serde_with::skip_serializing_none;
+use std::fmt::{self, Formatter};
+
+/// Fields used for the event.
+#[non_exhaustive]
+#[skip_serializing_none]
+#[derive(Clone, Debug, PartialEq, Serialize)]
+pub struct ProductAnalyticsServerSideEventItemEvent {
+ /// The name of your event, which is used for search in the same way as view or action names.
+ #[serde(rename = "name")]
+ pub name: String,
+ #[serde(flatten)]
+ pub additional_properties: std::collections::BTreeMap,
+ #[serde(skip)]
+ #[serde(default)]
+ pub(crate) _unparsed: bool,
+}
+
+impl ProductAnalyticsServerSideEventItemEvent {
+ pub fn new(name: String) -> ProductAnalyticsServerSideEventItemEvent {
+ ProductAnalyticsServerSideEventItemEvent {
+ name,
+ additional_properties: std::collections::BTreeMap::new(),
+ _unparsed: false,
+ }
+ }
+
+ pub fn additional_properties(
+ mut self,
+ value: std::collections::BTreeMap,
+ ) -> Self {
+ self.additional_properties = value;
+ self
+ }
+}
+
+impl<'de> Deserialize<'de> for ProductAnalyticsServerSideEventItemEvent {
+ fn deserialize(deserializer: D) -> Result
+ where
+ D: Deserializer<'de>,
+ {
+ struct ProductAnalyticsServerSideEventItemEventVisitor;
+ impl<'a> Visitor<'a> for ProductAnalyticsServerSideEventItemEventVisitor {
+ type Value = ProductAnalyticsServerSideEventItemEvent;
+
+ fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ f.write_str("a mapping")
+ }
+
+ fn visit_map(self, mut map: M) -> Result
+ where
+ M: MapAccess<'a>,
+ {
+ let mut name: Option = None;
+ let mut additional_properties: std::collections::BTreeMap<
+ String,
+ serde_json::Value,
+ > = std::collections::BTreeMap::new();
+ let mut _unparsed = false;
+
+ while let Some((k, v)) = map.next_entry::()? {
+ match k.as_str() {
+ "name" => {
+ name = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
+ }
+ &_ => {
+ if let Ok(value) = serde_json::from_value(v.clone()) {
+ additional_properties.insert(k, value);
+ }
+ }
+ }
+ }
+ let name = name.ok_or_else(|| M::Error::missing_field("name"))?;
+
+ let content = ProductAnalyticsServerSideEventItemEvent {
+ name,
+ additional_properties,
+ _unparsed,
+ };
+
+ Ok(content)
+ }
+ }
+
+ deserializer.deserialize_any(ProductAnalyticsServerSideEventItemEventVisitor)
+ }
+}
diff --git a/src/datadogV2/model/model_product_analytics_server_side_event_item_session.rs b/src/datadogV2/model/model_product_analytics_server_side_event_item_session.rs
new file mode 100644
index 000000000..da362c15d
--- /dev/null
+++ b/src/datadogV2/model/model_product_analytics_server_side_event_item_session.rs
@@ -0,0 +1,92 @@
+// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License.
+// This product includes software developed at Datadog (https://www.datadoghq.com/).
+// Copyright 2019-Present Datadog, Inc.
+use serde::de::{Error, MapAccess, Visitor};
+use serde::{Deserialize, Deserializer, Serialize};
+use serde_with::skip_serializing_none;
+use std::fmt::{self, Formatter};
+
+/// The session linked to your event.
+#[non_exhaustive]
+#[skip_serializing_none]
+#[derive(Clone, Debug, PartialEq, Serialize)]
+pub struct ProductAnalyticsServerSideEventItemSession {
+ /// The session ID captured by the SDK.
+ #[serde(rename = "id")]
+ pub id: String,
+ #[serde(flatten)]
+ pub additional_properties: std::collections::BTreeMap,
+ #[serde(skip)]
+ #[serde(default)]
+ pub(crate) _unparsed: bool,
+}
+
+impl ProductAnalyticsServerSideEventItemSession {
+ pub fn new(id: String) -> ProductAnalyticsServerSideEventItemSession {
+ ProductAnalyticsServerSideEventItemSession {
+ id,
+ additional_properties: std::collections::BTreeMap::new(),
+ _unparsed: false,
+ }
+ }
+
+ pub fn additional_properties(
+ mut self,
+ value: std::collections::BTreeMap,
+ ) -> Self {
+ self.additional_properties = value;
+ self
+ }
+}
+
+impl<'de> Deserialize<'de> for ProductAnalyticsServerSideEventItemSession {
+ fn deserialize(deserializer: D) -> Result
+ where
+ D: Deserializer<'de>,
+ {
+ struct ProductAnalyticsServerSideEventItemSessionVisitor;
+ impl<'a> Visitor<'a> for ProductAnalyticsServerSideEventItemSessionVisitor {
+ type Value = ProductAnalyticsServerSideEventItemSession;
+
+ fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ f.write_str("a mapping")
+ }
+
+ fn visit_map(self, mut map: M) -> Result
+ where
+ M: MapAccess<'a>,
+ {
+ let mut id: Option = None;
+ let mut additional_properties: std::collections::BTreeMap<
+ String,
+ serde_json::Value,
+ > = std::collections::BTreeMap::new();
+ let mut _unparsed = false;
+
+ while let Some((k, v)) = map.next_entry::()? {
+ match k.as_str() {
+ "id" => {
+ id = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
+ }
+ &_ => {
+ if let Ok(value) = serde_json::from_value(v.clone()) {
+ additional_properties.insert(k, value);
+ }
+ }
+ }
+ }
+ let id = id.ok_or_else(|| M::Error::missing_field("id"))?;
+
+ let content = ProductAnalyticsServerSideEventItemSession {
+ id,
+ additional_properties,
+ _unparsed,
+ };
+
+ Ok(content)
+ }
+ }
+
+ deserializer.deserialize_any(ProductAnalyticsServerSideEventItemSessionVisitor)
+ }
+}
diff --git a/src/datadogV2/model/model_product_analytics_server_side_event_item_type.rs b/src/datadogV2/model/model_product_analytics_server_side_event_item_type.rs
new file mode 100644
index 000000000..315961384
--- /dev/null
+++ b/src/datadogV2/model/model_product_analytics_server_side_event_item_type.rs
@@ -0,0 +1,48 @@
+// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License.
+// This product includes software developed at Datadog (https://www.datadoghq.com/).
+// Copyright 2019-Present Datadog, Inc.
+
+use serde::{Deserialize, Deserializer, Serialize, Serializer};
+
+#[non_exhaustive]
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum ProductAnalyticsServerSideEventItemType {
+ SERVER,
+ UnparsedObject(crate::datadog::UnparsedObject),
+}
+
+impl ToString for ProductAnalyticsServerSideEventItemType {
+ fn to_string(&self) -> String {
+ match self {
+ Self::SERVER => String::from("server"),
+ Self::UnparsedObject(v) => v.value.to_string(),
+ }
+ }
+}
+
+impl Serialize for ProductAnalyticsServerSideEventItemType {
+ fn serialize(&self, serializer: S) -> Result
+ where
+ S: Serializer,
+ {
+ match self {
+ Self::UnparsedObject(v) => v.serialize(serializer),
+ _ => serializer.serialize_str(self.to_string().as_str()),
+ }
+ }
+}
+
+impl<'de> Deserialize<'de> for ProductAnalyticsServerSideEventItemType {
+ fn deserialize(deserializer: D) -> Result
+ where
+ D: Deserializer<'de>,
+ {
+ let s: String = String::deserialize(deserializer)?;
+ Ok(match s.as_str() {
+ "server" => Self::SERVER,
+ _ => Self::UnparsedObject(crate::datadog::UnparsedObject {
+ value: serde_json::Value::String(s.into()),
+ }),
+ })
+ }
+}
diff --git a/src/datadogV2/model/model_product_analytics_server_side_event_item_usr.rs b/src/datadogV2/model/model_product_analytics_server_side_event_item_usr.rs
new file mode 100644
index 000000000..6e69ce4ab
--- /dev/null
+++ b/src/datadogV2/model/model_product_analytics_server_side_event_item_usr.rs
@@ -0,0 +1,92 @@
+// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License.
+// This product includes software developed at Datadog (https://www.datadoghq.com/).
+// Copyright 2019-Present Datadog, Inc.
+use serde::de::{Error, MapAccess, Visitor};
+use serde::{Deserialize, Deserializer, Serialize};
+use serde_with::skip_serializing_none;
+use std::fmt::{self, Formatter};
+
+/// The user linked to your event.
+#[non_exhaustive]
+#[skip_serializing_none]
+#[derive(Clone, Debug, PartialEq, Serialize)]
+pub struct ProductAnalyticsServerSideEventItemUsr {
+ /// The user ID used in Datadog.
+ #[serde(rename = "id")]
+ pub id: String,
+ #[serde(flatten)]
+ pub additional_properties: std::collections::BTreeMap,
+ #[serde(skip)]
+ #[serde(default)]
+ pub(crate) _unparsed: bool,
+}
+
+impl ProductAnalyticsServerSideEventItemUsr {
+ pub fn new(id: String) -> ProductAnalyticsServerSideEventItemUsr {
+ ProductAnalyticsServerSideEventItemUsr {
+ id,
+ additional_properties: std::collections::BTreeMap::new(),
+ _unparsed: false,
+ }
+ }
+
+ pub fn additional_properties(
+ mut self,
+ value: std::collections::BTreeMap,
+ ) -> Self {
+ self.additional_properties = value;
+ self
+ }
+}
+
+impl<'de> Deserialize<'de> for ProductAnalyticsServerSideEventItemUsr {
+ fn deserialize(deserializer: D) -> Result
+ where
+ D: Deserializer<'de>,
+ {
+ struct ProductAnalyticsServerSideEventItemUsrVisitor;
+ impl<'a> Visitor<'a> for ProductAnalyticsServerSideEventItemUsrVisitor {
+ type Value = ProductAnalyticsServerSideEventItemUsr;
+
+ fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ f.write_str("a mapping")
+ }
+
+ fn visit_map(self, mut map: M) -> Result
+ where
+ M: MapAccess<'a>,
+ {
+ let mut id: Option = None;
+ let mut additional_properties: std::collections::BTreeMap<
+ String,
+ serde_json::Value,
+ > = std::collections::BTreeMap::new();
+ let mut _unparsed = false;
+
+ while let Some((k, v)) = map.next_entry::()? {
+ match k.as_str() {
+ "id" => {
+ id = Some(serde_json::from_value(v).map_err(M::Error::custom)?);
+ }
+ &_ => {
+ if let Ok(value) = serde_json::from_value(v.clone()) {
+ additional_properties.insert(k, value);
+ }
+ }
+ }
+ }
+ let id = id.ok_or_else(|| M::Error::missing_field("id"))?;
+
+ let content = ProductAnalyticsServerSideEventItemUsr {
+ id,
+ additional_properties,
+ _unparsed,
+ };
+
+ Ok(content)
+ }
+ }
+
+ deserializer.deserialize_any(ProductAnalyticsServerSideEventItemUsrVisitor)
+ }
+}
diff --git a/tests/scenarios/features/v2/product_analytics.feature b/tests/scenarios/features/v2/product_analytics.feature
new file mode 100644
index 000000000..a915c2130
--- /dev/null
+++ b/tests/scenarios/features/v2/product_analytics.feature
@@ -0,0 +1,35 @@
+@endpoint(product-analytics) @endpoint(product-analytics-v2)
+Feature: Product Analytics
+ Send server-side events to Product Analytics. Server-Side Events Ingestion
+ allows you to collect custom events from any server-side source, and
+ retains events for 15 months. Server-side events are helpful for
+ understanding causes of a funnel drop-off which are external to the
+ client-side (for example, payment processing error). See the [Product
+ Analytics page](https://docs.datadoghq.com/product_analytics/) for more
+ information.
+
+ Background:
+ Given a valid "apiKeyAuth" key in the system
+ And an instance of "ProductAnalytics" API
+ And new "SubmitProductAnalyticsEvent" request
+ And body with value {"account": {"id": "account-67890"}, "application": {"id": "123abcde-123a-123b-1234-123456789abc"}, "event": {"name": "payment.processed"}, "session": {"id": "session-abcdef"}, "type": "server", "usr": {"id": "user-12345"}}
+
+ @generated @skip @team:DataDog/product-analytics-backend
+ Scenario: Send server-side events returns "Bad Request" response
+ When the request is sent
+ Then the response status is 400 Bad Request
+
+ @generated @skip @team:DataDog/product-analytics-backend
+ Scenario: Send server-side events returns "Payload Too Large" response
+ When the request is sent
+ Then the response status is 413 Payload Too Large
+
+ @generated @skip @team:DataDog/product-analytics-backend
+ Scenario: Send server-side events returns "Request Timeout" response
+ When the request is sent
+ Then the response status is 408 Request Timeout
+
+ @generated @skip @team:DataDog/product-analytics-backend
+ Scenario: Send server-side events returns "Request accepted for processing (always 202 empty JSON)." response
+ When the request is sent
+ Then the response status is 202 Request accepted for processing (always 202 empty JSON).
diff --git a/tests/scenarios/features/v2/undo.json b/tests/scenarios/features/v2/undo.json
index eb43f26db..0867c10cd 100644
--- a/tests/scenarios/features/v2/undo.json
+++ b/tests/scenarios/features/v2/undo.json
@@ -3133,6 +3133,12 @@
"type": "safe"
}
},
+ "SubmitProductAnalyticsEvent": {
+ "tag": "Product Analytics",
+ "undo": {
+ "type": "safe"
+ }
+ },
"GetAccountFacetInfo": {
"tag": "Rum Audience Management",
"undo": {
diff --git a/tests/scenarios/function_mappings.rs b/tests/scenarios/function_mappings.rs
index 312f0d588..555291ee6 100644
--- a/tests/scenarios/function_mappings.rs
+++ b/tests/scenarios/function_mappings.rs
@@ -126,6 +126,7 @@ pub struct ApiInstances {
pub v2_api_roles: Option,
pub v2_api_powerpack: Option,
pub v2_api_processes: Option,
+ pub v2_api_product_analytics: Option,
pub v2_api_rum_audience_management:
Option,
pub v2_api_reference_tables: Option,
@@ -846,6 +847,14 @@ pub fn initialize_api_instance(world: &mut DatadogWorld, api: String) {
),
);
}
+ "ProductAnalytics" => {
+ world.api_instances.v2_api_product_analytics = Some(
+ datadogV2::api_product_analytics::ProductAnalyticsAPI::with_client_and_config(
+ world.config.clone(),
+ world.http_client.as_ref().unwrap().clone(),
+ ),
+ );
+ }
"RumAudienceManagement" => {
world.api_instances.v2_api_rum_audience_management = Some(datadogV2::api_rum_audience_management::RumAudienceManagementAPI::with_client_and_config(
world.config.clone(),
@@ -3926,6 +3935,10 @@ pub fn collect_function_calls(world: &mut DatadogWorld) {
"v2.ListProcessesWithPagination".into(),
test_v2_list_processes_with_pagination,
);
+ world.function_mappings.insert(
+ "v2.SubmitProductAnalyticsEvent".into(),
+ test_v2_submit_product_analytics_event,
+ );
world.function_mappings.insert(
"v2.GetAccountFacetInfo".into(),
test_v2_get_account_facet_info,
@@ -30041,6 +30054,34 @@ fn test_v2_list_processes_with_pagination(
world.response.code = 200;
}
+fn test_v2_submit_product_analytics_event(
+ world: &mut DatadogWorld,
+ _parameters: &HashMap,
+) {
+ let api = world
+ .api_instances
+ .v2_api_product_analytics
+ .as_ref()
+ .expect("api instance not found");
+ let body = serde_json::from_value(_parameters.get("body").unwrap().clone()).unwrap();
+ let response = match block_on(api.submit_product_analytics_event_with_http_info(body)) {
+ Ok(response) => response,
+ Err(error) => {
+ return match error {
+ Error::ResponseError(e) => {
+ world.response.code = e.status.as_u16();
+ if let Some(entity) = e.entity {
+ world.response.object = serde_json::to_value(entity).unwrap();
+ }
+ }
+ _ => panic!("error parsing response: {error}"),
+ };
+ }
+ };
+ world.response.object = serde_json::to_value(response.entity).unwrap();
+ world.response.code = response.status.as_u16();
+}
+
fn test_v2_get_account_facet_info(world: &mut DatadogWorld, _parameters: &HashMap) {
let api = world
.api_instances