diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index 22a9f1e6a48..531154bda8c 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -2396,6 +2396,116 @@ components: $ref: "#/components/schemas/JSONAPIErrorResponse" description: The server cannot process the request because it contains invalid data. schemas: + AIImpactUserActivityAttributes: + additionalProperties: false + description: |- + Daily AI coding tool activity for a single user. Each entry reports whether the user was + active on a given day and which AI tools and models they used. + properties: + day: + description: The day the activity refers to, in `YYYY-MM-DD` format. + example: "2026-05-26" + pattern: "^\\d{4}-\\d{2}-\\d{2}$" + type: string + is_active: + description: Whether the user actively used the listed AI tools on that day. + example: true + type: boolean + models: + $ref: "#/components/schemas/AIImpactUserActivityModels" + tools: + $ref: "#/components/schemas/AIImpactUserActivityTools" + user_email: + description: |- + The email address of the user. It is case-insensitive and is matched against the + email addresses of commit authors. + example: user@example.com + pattern: "^[^@]+@[^@.]+(?:\\.[^@.]+)+$" + type: string + required: + - user_email + - is_active + - day + - tools + type: object + AIImpactUserActivityData: + additionalProperties: false + description: A single daily AI tool activity entry. + properties: + attributes: + $ref: "#/components/schemas/AIImpactUserActivityAttributes" + type: + $ref: "#/components/schemas/AIImpactUserActivityType" + required: + - type + - attributes + type: object + AIImpactUserActivityDataArray: + description: |- + A batch of daily AI tool activity entries. A batch must contain between 1 and 1,000 entries. + example: + - attributes: + day: "2026-05-26" + is_active: true + models: + - claude-sonnet-4.5 + - gpt-5 + tools: + - Claude Code + - Cursor + user_email: user@example.com + type: ai_impact_user_activity + items: + $ref: "#/components/schemas/AIImpactUserActivityData" + maxItems: 1000 + minItems: 1 + type: array + AIImpactUserActivityModels: + description: |- + The AI models the user used on that day, for example `claude-sonnet-4.5` or `gpt-5`. + Values are lowercased and duplicates are removed. + example: + - claude-sonnet-4.5 + - gpt-5 + items: + description: The name of an AI model. + example: claude-sonnet-4.5 + type: string + type: array + AIImpactUserActivityRequest: + additionalProperties: false + description: Request to send daily AI tool activity for one or more users. + properties: + data: + $ref: "#/components/schemas/AIImpactUserActivityDataArray" + required: + - data + type: object + AIImpactUserActivityTools: + description: |- + The AI coding tools the user used on that day, for example `Claude Code`, `Cursor`, or + `GitHub Copilot`. Known tools are normalized to a canonical name (`claude_code`, `cursor`, + `copilot`), and other values are converted to snake case. Entries must not be empty. + example: + - Claude Code + - Cursor + items: + description: The name of an AI coding tool. + example: Claude Code + minLength: 1 + pattern: ".*\\S.*" + type: string + minItems: 1 + type: array + AIImpactUserActivityType: + default: ai_impact_user_activity + description: JSON:API type for AI Impact user activity entries. + enum: + - ai_impact_user_activity + example: ai_impact_user_activity + type: string + x-enum-varnames: + - AI_IMPACT_USER_ACTIVITY APIErrorResponse: description: API error response. properties: @@ -141616,6 +141726,59 @@ paths: operator: OR permissions: - security_monitoring_findings_read + /api/v2/ai_impact/user_activity: + post: + description: |- + Send daily AI coding tool activity for one or more users. Each entry records whether a + user was active on a given day, along with the AI tools and models they used. An entry + is stored once per tool, and sending the same user, day, and tool again overwrites the + previous value. + operationId: CreateAIImpactUserActivity + requestBody: + content: + application/json: + examples: + default: + value: + data: + - attributes: + day: "2026-05-26" + is_active: true + models: + - claude-sonnet-4.5 + - gpt-5 + tools: + - Claude Code + - Cursor + user_email: user@example.com + type: ai_impact_user_activity + schema: + $ref: "#/components/schemas/AIImpactUserActivityRequest" + required: true + responses: + "200": + description: OK + "400": + content: + application/json: + schema: + $ref: "#/components/schemas/JSONAPIErrorResponse" + description: |- + Bad Request: the batch is empty, has more than 1,000 entries, or contains an invalid entry. + An entry is invalid when `user_email`, `is_active`, or `day` is missing, `tools` is missing + or an empty array, `user_email` is not a valid email address, `day` is not in `YYYY-MM-DD` + format, or a tool name is empty. The error message identifies the index of the first invalid + entry. Fix the payload and send the request again. + "403": + $ref: "#/components/responses/NotAuthorizedResponse" + "429": + $ref: "#/components/responses/TooManyRequestsResponse" + security: + - apiKeyAuth: [] + summary: Send AI tool user activity + tags: + - AI Impact + x-codegen-request-body-name: body /api/v2/annotation: get: description: Returns a flat list of annotations matching the given page, time window, and optional widget filter. @@ -244846,6 +245009,9 @@ servers: default: api description: The subdomain where the API is deployed. tags: + - description: |- + Send AI coding tool usage data to measure the impact of AI tools on software delivery. + name: AI Impact - description: |- Configure your API endpoints through the Datadog API. name: API Management diff --git a/examples/v2/ai-impact/CreateAIImpactUserActivity.java b/examples/v2/ai-impact/CreateAIImpactUserActivity.java new file mode 100644 index 00000000000..ceb896dc175 --- /dev/null +++ b/examples/v2/ai-impact/CreateAIImpactUserActivity.java @@ -0,0 +1,42 @@ +// Send AI tool user activity returns "OK" response + +import com.datadog.api.client.ApiClient; +import com.datadog.api.client.ApiException; +import com.datadog.api.client.v2.api.AiImpactApi; +import com.datadog.api.client.v2.model.AIImpactUserActivityAttributes; +import com.datadog.api.client.v2.model.AIImpactUserActivityData; +import com.datadog.api.client.v2.model.AIImpactUserActivityRequest; +import com.datadog.api.client.v2.model.AIImpactUserActivityType; +import java.util.Arrays; +import java.util.Collections; + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = ApiClient.getDefaultApiClient(); + AiImpactApi apiInstance = new AiImpactApi(defaultClient); + + AIImpactUserActivityRequest body = + new AIImpactUserActivityRequest() + .data( + Collections.singletonList( + new AIImpactUserActivityData() + .attributes( + new AIImpactUserActivityAttributes() + .day("2026-05-26") + .isActive(true) + .models(Arrays.asList("claude-sonnet-4.5", "gpt-5")) + .tools(Arrays.asList("Claude Code", "Cursor")) + .userEmail("user@example.com")) + .type(AIImpactUserActivityType.AI_IMPACT_USER_ACTIVITY))); + + try { + apiInstance.createAIImpactUserActivity(body); + } catch (ApiException e) { + System.err.println("Exception when calling AiImpactApi#createAIImpactUserActivity"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/datadog/api/client/v2/api/AiImpactApi.java b/src/main/java/com/datadog/api/client/v2/api/AiImpactApi.java new file mode 100644 index 00000000000..4e9ef7c397b --- /dev/null +++ b/src/main/java/com/datadog/api/client/v2/api/AiImpactApi.java @@ -0,0 +1,177 @@ +package com.datadog.api.client.v2.api; + +import com.datadog.api.client.ApiClient; +import com.datadog.api.client.ApiException; +import com.datadog.api.client.ApiResponse; +import com.datadog.api.client.Pair; +import com.datadog.api.client.v2.model.AIImpactUserActivityRequest; +import jakarta.ws.rs.client.Invocation; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +@jakarta.annotation.Generated( + value = "https://github.com/DataDog/datadog-api-client-java/blob/master/.generator") +public class AiImpactApi { + private ApiClient apiClient; + + public AiImpactApi() { + this(ApiClient.getDefaultApiClient()); + } + + public AiImpactApi(ApiClient apiClient) { + this.apiClient = apiClient; + } + + /** + * Get the API client. + * + * @return API client + */ + public ApiClient getApiClient() { + return apiClient; + } + + /** + * Set the API client. + * + * @param apiClient an instance of API client + */ + public void setApiClient(ApiClient apiClient) { + this.apiClient = apiClient; + } + + /** + * Send AI tool user activity. + * + *

See {@link #createAIImpactUserActivityWithHttpInfo}. + * + * @param body (required) + * @throws ApiException if fails to make API call + */ + public void createAIImpactUserActivity(AIImpactUserActivityRequest body) throws ApiException { + createAIImpactUserActivityWithHttpInfo(body); + } + + /** + * Send AI tool user activity. + * + *

See {@link #createAIImpactUserActivityWithHttpInfoAsync}. + * + * @param body (required) + * @return CompletableFuture + */ + public CompletableFuture createAIImpactUserActivityAsync(AIImpactUserActivityRequest body) { + return createAIImpactUserActivityWithHttpInfoAsync(body) + .thenApply( + response -> { + return response.getData(); + }); + } + + /** + * Send daily AI coding tool activity for one or more users. Each entry records whether a user was + * active on a given day, along with the AI tools and models they used. An entry is stored once + * per tool, and sending the same user, day, and tool again overwrites the previous value. + * + * @param body (required) + * @return ApiResponse<Void> + * @throws ApiException if fails to make API call + * @http.response.details + * + * + * + * + * + * + * + *
Response details
Status Code Description Response Headers
200 OK -
400 Bad Request: the batch is empty, has more than 1,000 entries, or contains an invalid entry. An entry is invalid when `user_email`, `is_active`, or `day` is missing, `tools` is missing or an empty array, `user_email` is not a valid email address, `day` is not in `YYYY-MM-DD` format, or a tool name is empty. The error message identifies the index of the first invalid entry. Fix the payload and send the request again. -
403 Not Authorized -
429 Too many requests -
+ */ + public ApiResponse createAIImpactUserActivityWithHttpInfo(AIImpactUserActivityRequest body) + throws ApiException { + Object localVarPostBody = body; + + // verify the required parameter 'body' is set + if (body == null) { + throw new ApiException( + 400, "Missing the required parameter 'body' when calling createAIImpactUserActivity"); + } + // create path and map variables + String localVarPath = "/api/v2/ai_impact/user_activity"; + + Map localVarHeaderParams = new HashMap(); + + Invocation.Builder builder = + apiClient.createBuilder( + "v2.AiImpactApi.createAIImpactUserActivity", + localVarPath, + new ArrayList(), + localVarHeaderParams, + new HashMap(), + new String[] {"*/*"}, + new String[] {"apiKeyAuth"}); + return apiClient.invokeAPI( + "POST", + builder, + localVarHeaderParams, + new String[] {"application/json"}, + localVarPostBody, + new HashMap(), + false, + null); + } + + /** + * Send AI tool user activity. + * + *

See {@link #createAIImpactUserActivityWithHttpInfo}. + * + * @param body (required) + * @return CompletableFuture<ApiResponse<Void>> + */ + public CompletableFuture> createAIImpactUserActivityWithHttpInfoAsync( + AIImpactUserActivityRequest body) { + Object localVarPostBody = body; + + // verify the required parameter 'body' is set + if (body == null) { + CompletableFuture> result = new CompletableFuture<>(); + result.completeExceptionally( + new ApiException( + 400, + "Missing the required parameter 'body' when calling createAIImpactUserActivity")); + return result; + } + // create path and map variables + String localVarPath = "/api/v2/ai_impact/user_activity"; + + Map localVarHeaderParams = new HashMap(); + + Invocation.Builder builder; + try { + builder = + apiClient.createBuilder( + "v2.AiImpactApi.createAIImpactUserActivity", + localVarPath, + new ArrayList(), + localVarHeaderParams, + new HashMap(), + new String[] {"*/*"}, + new String[] {"apiKeyAuth"}); + } catch (ApiException ex) { + CompletableFuture> result = new CompletableFuture<>(); + result.completeExceptionally(ex); + return result; + } + return apiClient.invokeAPIAsync( + "POST", + builder, + localVarHeaderParams, + new String[] {"application/json"}, + localVarPostBody, + new HashMap(), + false, + null); + } +} diff --git a/src/main/java/com/datadog/api/client/v2/model/AIImpactUserActivityAttributes.java b/src/main/java/com/datadog/api/client/v2/model/AIImpactUserActivityAttributes.java new file mode 100644 index 00000000000..cf29c81b804 --- /dev/null +++ b/src/main/java/com/datadog/api/client/v2/model/AIImpactUserActivityAttributes.java @@ -0,0 +1,226 @@ +/* + * 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. + */ + +package com.datadog.api.client.v2.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * Daily AI coding tool activity for a single user. Each entry reports whether the user was active + * on a given day and which AI tools and models they used. + */ +@JsonPropertyOrder({ + AIImpactUserActivityAttributes.JSON_PROPERTY_DAY, + AIImpactUserActivityAttributes.JSON_PROPERTY_IS_ACTIVE, + AIImpactUserActivityAttributes.JSON_PROPERTY_MODELS, + AIImpactUserActivityAttributes.JSON_PROPERTY_TOOLS, + AIImpactUserActivityAttributes.JSON_PROPERTY_USER_EMAIL +}) +@jakarta.annotation.Generated( + value = "https://github.com/DataDog/datadog-api-client-java/blob/master/.generator") +public class AIImpactUserActivityAttributes { + @JsonIgnore public boolean unparsed = false; + public static final String JSON_PROPERTY_DAY = "day"; + private String day; + + public static final String JSON_PROPERTY_IS_ACTIVE = "is_active"; + private Boolean isActive; + + public static final String JSON_PROPERTY_MODELS = "models"; + private List models = null; + + public static final String JSON_PROPERTY_TOOLS = "tools"; + private List tools = new ArrayList<>(); + + public static final String JSON_PROPERTY_USER_EMAIL = "user_email"; + private String userEmail; + + public AIImpactUserActivityAttributes() {} + + @JsonCreator + public AIImpactUserActivityAttributes( + @JsonProperty(required = true, value = JSON_PROPERTY_DAY) String day, + @JsonProperty(required = true, value = JSON_PROPERTY_IS_ACTIVE) Boolean isActive, + @JsonProperty(required = true, value = JSON_PROPERTY_TOOLS) List tools, + @JsonProperty(required = true, value = JSON_PROPERTY_USER_EMAIL) String userEmail) { + this.day = day; + this.isActive = isActive; + this.tools = tools; + this.userEmail = userEmail; + } + + public AIImpactUserActivityAttributes day(String day) { + this.day = day; + return this; + } + + /** + * The day the activity refers to, in YYYY-MM-DD format. + * + * @return day + */ + @JsonProperty(JSON_PROPERTY_DAY) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public String getDay() { + return day; + } + + public void setDay(String day) { + this.day = day; + } + + public AIImpactUserActivityAttributes isActive(Boolean isActive) { + this.isActive = isActive; + return this; + } + + /** + * Whether the user actively used the listed AI tools on that day. + * + * @return isActive + */ + @JsonProperty(JSON_PROPERTY_IS_ACTIVE) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public Boolean getIsActive() { + return isActive; + } + + public void setIsActive(Boolean isActive) { + this.isActive = isActive; + } + + public AIImpactUserActivityAttributes models(List models) { + this.models = models; + return this; + } + + public AIImpactUserActivityAttributes addModelsItem(String modelsItem) { + if (this.models == null) { + this.models = new ArrayList<>(); + } + this.models.add(modelsItem); + return this; + } + + /** + * The AI models the user used on that day, for example claude-sonnet-4.5 or + * gpt-5. Values are lowercased and duplicates are removed. + * + * @return models + */ + @jakarta.annotation.Nullable + @JsonProperty(JSON_PROPERTY_MODELS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public List getModels() { + return models; + } + + public void setModels(List models) { + this.models = models; + } + + public AIImpactUserActivityAttributes tools(List tools) { + this.tools = tools; + return this; + } + + public AIImpactUserActivityAttributes addToolsItem(String toolsItem) { + this.tools.add(toolsItem); + return this; + } + + /** + * The AI coding tools the user used on that day, for example Claude Code, + * Cursor, or GitHub Copilot. Known tools are normalized to a canonical name ( + * claude_code, cursor, copilot), and other values are + * converted to snake case. Entries must not be empty. + * + * @return tools + */ + @JsonProperty(JSON_PROPERTY_TOOLS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public List getTools() { + return tools; + } + + public void setTools(List tools) { + this.tools = tools; + } + + public AIImpactUserActivityAttributes userEmail(String userEmail) { + this.userEmail = userEmail; + return this; + } + + /** + * The email address of the user. It is case-insensitive and is matched against the email + * addresses of commit authors. + * + * @return userEmail + */ + @JsonProperty(JSON_PROPERTY_USER_EMAIL) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public String getUserEmail() { + return userEmail; + } + + public void setUserEmail(String userEmail) { + this.userEmail = userEmail; + } + + /** Return true if this AIImpactUserActivityAttributes object is equal to o. */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AIImpactUserActivityAttributes aiImpactUserActivityAttributes = + (AIImpactUserActivityAttributes) o; + return Objects.equals(this.day, aiImpactUserActivityAttributes.day) + && Objects.equals(this.isActive, aiImpactUserActivityAttributes.isActive) + && Objects.equals(this.models, aiImpactUserActivityAttributes.models) + && Objects.equals(this.tools, aiImpactUserActivityAttributes.tools) + && Objects.equals(this.userEmail, aiImpactUserActivityAttributes.userEmail); + } + + @Override + public int hashCode() { + return Objects.hash(day, isActive, models, tools, userEmail); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class AIImpactUserActivityAttributes {\n"); + sb.append(" day: ").append(toIndentedString(day)).append("\n"); + sb.append(" isActive: ").append(toIndentedString(isActive)).append("\n"); + sb.append(" models: ").append(toIndentedString(models)).append("\n"); + sb.append(" tools: ").append(toIndentedString(tools)).append("\n"); + sb.append(" userEmail: ").append(toIndentedString(userEmail)).append("\n"); + sb.append('}'); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/src/main/java/com/datadog/api/client/v2/model/AIImpactUserActivityData.java b/src/main/java/com/datadog/api/client/v2/model/AIImpactUserActivityData.java new file mode 100644 index 00000000000..016e6eeabd7 --- /dev/null +++ b/src/main/java/com/datadog/api/client/v2/model/AIImpactUserActivityData.java @@ -0,0 +1,131 @@ +/* + * 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. + */ + +package com.datadog.api.client.v2.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.util.Objects; + +/** A single daily AI tool activity entry. */ +@JsonPropertyOrder({ + AIImpactUserActivityData.JSON_PROPERTY_ATTRIBUTES, + AIImpactUserActivityData.JSON_PROPERTY_TYPE +}) +@jakarta.annotation.Generated( + value = "https://github.com/DataDog/datadog-api-client-java/blob/master/.generator") +public class AIImpactUserActivityData { + @JsonIgnore public boolean unparsed = false; + public static final String JSON_PROPERTY_ATTRIBUTES = "attributes"; + private AIImpactUserActivityAttributes attributes; + + public static final String JSON_PROPERTY_TYPE = "type"; + private AIImpactUserActivityType type = AIImpactUserActivityType.AI_IMPACT_USER_ACTIVITY; + + public AIImpactUserActivityData() {} + + @JsonCreator + public AIImpactUserActivityData( + @JsonProperty(required = true, value = JSON_PROPERTY_ATTRIBUTES) + AIImpactUserActivityAttributes attributes, + @JsonProperty(required = true, value = JSON_PROPERTY_TYPE) AIImpactUserActivityType type) { + this.attributes = attributes; + this.unparsed |= attributes.unparsed; + this.type = type; + this.unparsed |= !type.isValid(); + } + + public AIImpactUserActivityData attributes(AIImpactUserActivityAttributes attributes) { + this.attributes = attributes; + this.unparsed |= attributes.unparsed; + return this; + } + + /** + * Daily AI coding tool activity for a single user. Each entry reports whether the user was active + * on a given day and which AI tools and models they used. + * + * @return attributes + */ + @JsonProperty(JSON_PROPERTY_ATTRIBUTES) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public AIImpactUserActivityAttributes getAttributes() { + return attributes; + } + + public void setAttributes(AIImpactUserActivityAttributes attributes) { + this.attributes = attributes; + if (attributes != null) { + this.unparsed |= attributes.unparsed; + } + } + + public AIImpactUserActivityData type(AIImpactUserActivityType type) { + this.type = type; + this.unparsed |= !type.isValid(); + return this; + } + + /** + * JSON:API type for AI Impact user activity entries. + * + * @return type + */ + @JsonProperty(JSON_PROPERTY_TYPE) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public AIImpactUserActivityType getType() { + return type; + } + + public void setType(AIImpactUserActivityType type) { + if (!type.isValid()) { + this.unparsed = true; + } + this.type = type; + } + + /** Return true if this AIImpactUserActivityData object is equal to o. */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AIImpactUserActivityData aiImpactUserActivityData = (AIImpactUserActivityData) o; + return Objects.equals(this.attributes, aiImpactUserActivityData.attributes) + && Objects.equals(this.type, aiImpactUserActivityData.type); + } + + @Override + public int hashCode() { + return Objects.hash(attributes, type); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class AIImpactUserActivityData {\n"); + sb.append(" attributes: ").append(toIndentedString(attributes)).append("\n"); + sb.append(" type: ").append(toIndentedString(type)).append("\n"); + sb.append('}'); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/src/main/java/com/datadog/api/client/v2/model/AIImpactUserActivityRequest.java b/src/main/java/com/datadog/api/client/v2/model/AIImpactUserActivityRequest.java new file mode 100644 index 00000000000..f09de890b4a --- /dev/null +++ b/src/main/java/com/datadog/api/client/v2/model/AIImpactUserActivityRequest.java @@ -0,0 +1,109 @@ +/* + * 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. + */ + +package com.datadog.api.client.v2.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** Request to send daily AI tool activity for one or more users. */ +@JsonPropertyOrder({AIImpactUserActivityRequest.JSON_PROPERTY_DATA}) +@jakarta.annotation.Generated( + value = "https://github.com/DataDog/datadog-api-client-java/blob/master/.generator") +public class AIImpactUserActivityRequest { + @JsonIgnore public boolean unparsed = false; + public static final String JSON_PROPERTY_DATA = "data"; + private List data = new ArrayList<>(); + + public AIImpactUserActivityRequest() {} + + @JsonCreator + public AIImpactUserActivityRequest( + @JsonProperty(required = true, value = JSON_PROPERTY_DATA) + List data) { + this.data = data; + for (AIImpactUserActivityData item : data) { + this.unparsed |= item.unparsed; + } + } + + public AIImpactUserActivityRequest data(List data) { + this.data = data; + for (AIImpactUserActivityData item : data) { + this.unparsed |= item.unparsed; + } + return this; + } + + public AIImpactUserActivityRequest addDataItem(AIImpactUserActivityData dataItem) { + this.data.add(dataItem); + this.unparsed |= dataItem.unparsed; + return this; + } + + /** + * A batch of daily AI tool activity entries. A batch must contain between 1 and 1,000 entries. + * + * @return data + */ + @JsonProperty(JSON_PROPERTY_DATA) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + if (data != null) { + for (AIImpactUserActivityData item : data) { + this.unparsed |= item.unparsed; + } + } + } + + /** Return true if this AIImpactUserActivityRequest object is equal to o. */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AIImpactUserActivityRequest aiImpactUserActivityRequest = (AIImpactUserActivityRequest) o; + return Objects.equals(this.data, aiImpactUserActivityRequest.data); + } + + @Override + public int hashCode() { + return Objects.hash(data); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class AIImpactUserActivityRequest {\n"); + sb.append(" data: ").append(toIndentedString(data)).append("\n"); + sb.append('}'); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/src/main/java/com/datadog/api/client/v2/model/AIImpactUserActivityType.java b/src/main/java/com/datadog/api/client/v2/model/AIImpactUserActivityType.java new file mode 100644 index 00000000000..007abb21f82 --- /dev/null +++ b/src/main/java/com/datadog/api/client/v2/model/AIImpactUserActivityType.java @@ -0,0 +1,57 @@ +/* + * 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. + */ + +package com.datadog.api.client.v2.model; + +import com.datadog.api.client.ModelEnum; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import java.io.IOException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +/** JSON:API type for AI Impact user activity entries. */ +@JsonSerialize(using = AIImpactUserActivityType.AIImpactUserActivityTypeSerializer.class) +public class AIImpactUserActivityType extends ModelEnum { + + private static final Set allowedValues = + new HashSet(Arrays.asList("ai_impact_user_activity")); + + public static final AIImpactUserActivityType AI_IMPACT_USER_ACTIVITY = + new AIImpactUserActivityType("ai_impact_user_activity"); + + AIImpactUserActivityType(String value) { + super(value, allowedValues); + } + + public static class AIImpactUserActivityTypeSerializer + extends StdSerializer { + public AIImpactUserActivityTypeSerializer(Class t) { + super(t); + } + + public AIImpactUserActivityTypeSerializer() { + this(null); + } + + @Override + public void serialize( + AIImpactUserActivityType value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException { + jgen.writeObject(value.value); + } + } + + @JsonCreator + public static AIImpactUserActivityType fromValue(String value) { + return new AIImpactUserActivityType(value); + } +} diff --git a/src/test/resources/com/datadog/api/client/v2/api/ai_impact.feature b/src/test/resources/com/datadog/api/client/v2/api/ai_impact.feature new file mode 100644 index 00000000000..ee04200c6b9 --- /dev/null +++ b/src/test/resources/com/datadog/api/client/v2/api/ai_impact.feature @@ -0,0 +1,20 @@ +@endpoint(ai-impact) @endpoint(ai-impact-v2) +Feature: AI Impact + Send AI coding tool usage data to measure the impact of AI tools on + software delivery. + + Background: + Given a valid "apiKeyAuth" key in the system + And an instance of "AIImpact" API + And new "CreateAIImpactUserActivity" request + And body with value {"data": [{"attributes": {"day": "2026-05-26", "is_active": true, "models": ["claude-sonnet-4.5", "gpt-5"], "tools": ["Claude Code", "Cursor"], "user_email": "user@example.com"}, "type": "ai_impact_user_activity"}]} + + @generated @skip @team:ddoghq/ci-app-backend + Scenario: Send AI tool user activity returns "Bad Request: the batch is empty, has more than 1,000 entries, or contains an invalid entry." response + When the request is sent + Then the response status is 400 Bad Request: the batch is empty, has more than 1,000 entries, or contains an invalid entry. + + @generated @skip @team:ddoghq/ci-app-backend + Scenario: Send AI tool user activity returns "OK" response + When the request is sent + Then the response status is 200 OK diff --git a/src/test/resources/com/datadog/api/client/v2/api/undo.json b/src/test/resources/com/datadog/api/client/v2/api/undo.json index c7e0bfc8bb7..b54343dc540 100644 --- a/src/test/resources/com/datadog/api/client/v2/api/undo.json +++ b/src/test/resources/com/datadog/api/client/v2/api/undo.json @@ -368,6 +368,12 @@ "type": "safe" } }, + "CreateAIImpactUserActivity": { + "tag": "AI Impact", + "undo": { + "type": "idempotent" + } + }, "ListAnnotations": { "tag": "Annotations", "undo": {