diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index 1606032e9da3..c43341f91d85 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -15799,6 +15799,132 @@ components: example: "One or several indexes are missing or invalid, results hold data from the other indexes" type: string type: object + CILogAttributeValue: + description: A flat additional log attribute. Objects and arrays are not accepted. + oneOf: + - nullable: true + type: string + - format: double + type: number + - type: boolean + CILogContentEncoding: + description: HTTP header used to compress the JSON request body. + enum: + - identity + - gzip + type: string + x-enum-varnames: + - IDENTITY + - GZIP + CILogErrors: + description: Authentication and authorization errors returned by the CI logs intake API. + properties: + errors: + description: Error messages. + example: + - Forbidden + - API key is missing or invalid + items: + type: string + type: array + type: object + CILogIntakeError: + description: A request error returned by the CI logs intake API. + properties: + detail: + description: Error details. + example: Malformed payload + type: string + status: + description: HTTP status code. + example: "400" + type: string + title: + description: Error title. + example: Bad Request + type: string + type: object + CILogIntakeErrors: + description: Request errors returned by the CI logs intake API. + properties: + errors: + description: Request errors. + items: + $ref: "#/components/schemas/CILogIntakeError" + type: array + type: object + CILogItem: + additionalProperties: + $ref: "#/components/schemas/CILogAttributeValue" + description: A CI job log line. + maxProperties: 137 + properties: + ddtags: + description: Comma-separated `key:value` tags. A job can have up to 256 tags, including repeated keys. + example: runner:linux,architecture:amd64 + type: string + job_id: + description: The job event's `resource.id`, sent through the CI Visibility pipeline API. + example: job-456 + minLength: 1 + type: string + line_number: + description: The line number in the job log. Use 0 or 1 for the first line. + example: 812 + format: int64 + maximum: 9223372036854775807 + minimum: 0 + type: integer + message: + description: The non-empty log line message. + example: Running go test ./... + minLength: 1 + type: string + pipeline_unique_id: + description: |- + The `resource.unique_id` of the pipeline event, which must also match the job event's + `resource.pipeline_unique_id`. + example: 3eacb6f3-ff04-4e10-8a9c-46e6d054024a + minLength: 1 + type: string + provider_name: + description: |- + The provider name sent with the pipeline event. It defaults to `custom` when omitted and, when provided, + must be non-empty and cannot contain a comma. + example: example-provider + minLength: 1 + pattern: "^[^,]+$" + type: string + section_name: + description: |- + The provider-defined section containing this log line, used to display collapsible groups of lines in the CI + job log view. + example: tests + type: string + status: + description: |- + The status of this log line. Any string is accepted. Datadog maps non-empty values to a standard log status. + See [status mapping](https://docs.datadoghq.com/logs/log_configuration/processors/log_status_remapper/). + example: warn + type: string + timestamp: + description: |- + The log line time in RFC 3339 format with an explicit timezone. If omitted, the intake time is used. It can + be at most 18 hours in the past or 12 hours in the future. + format: date-time + type: string + required: + - message + - pipeline_unique_id + - job_id + type: object + CILogRequest: + description: |- + A batch of up to 1,000 CI job log lines. Use a one-item array to send one log line. + items: + $ref: "#/components/schemas/CILogItem" + maxItems: 1000 + type: array CSMAgentsMetadata: description: Metadata related to the paginated response. properties: @@ -150692,6 +150818,159 @@ paths: permissions: - ci_visibility_read - test_optimization_read + /api/v2/cilogs: + post: + description: |- + Send log lines for a CI job over HTTP. See the [CI Visibility Pipelines + API](https://docs.datadoghq.com/api/latest/ci-visibility-pipelines/send-pipeline-event/) for submitting the + associated pipeline and job events. + + A request can contain one log object or an array of up to 1,000 log objects. The maximum uncompressed request + body size is 5.1 MiB. + + You can stream log lines while a CI job runs or send them after it finishes. After you submit the completed job + event, 20 seconds without a new log line marks the job's logs as complete. Lines sent after that may not appear. + + A job can have up to 128 additional attributes and 256 tags. Additional attributes are top-level fields with + string, number, Boolean, or null values. Nested objects and arrays are rejected. Additional attributes and + `ddtags` apply to all log lines in the job. If an additional attribute has different values on different lines, + the first value received is used. Tags supplied on different lines are combined. A job can contain up to + 2,000,000 log records or 1 GiB of message bytes in total. + + To reduce request size, send gzip-compressed JSON with the `Content-Encoding: gzip` header. Retry requests after + a 408, 429, 500, or 503 response. + operationId: SubmitCILog + parameters: + - description: HTTP header used to compress the JSON request body. + in: header + name: Content-Encoding + required: false + schema: + $ref: "#/components/schemas/CILogContentEncoding" + requestBody: + content: + application/json: + examples: + default: + summary: Single CI job log line + value: + - ddtags: runner:linux,architecture:amd64 + job_id: job-456 + line_number: 812 + message: Running go test ./... + pipeline_unique_id: 3eacb6f3-ff04-4e10-8a9c-46e6d054024a + provider_name: example-provider + section_name: tests + status: warn + stream: stdout + multiple-logs: + summary: Multiple CI job log lines + value: + - job_id: job-456 + line_number: 1 + message: Running go test ./... + pipeline_unique_id: 3eacb6f3-ff04-4e10-8a9c-46e6d054024a + - job_id: job-456 + line_number: 2 + message: Tests passed + pipeline_unique_id: 3eacb6f3-ff04-4e10-8a9c-46e6d054024a + schema: + $ref: "#/components/schemas/CILogRequest" + description: CI job log line or batch in JSON format. + required: true + responses: + "202": + content: + application/json: + examples: + default: + value: {} + schema: + type: object + description: Request accepted for processing + "400": + content: + application/json: + schema: + $ref: "#/components/schemas/CILogIntakeErrors" + description: Bad Request + "401": + content: + application/json: + schema: + $ref: "#/components/schemas/CILogErrors" + description: Unauthorized + "403": + content: + application/json: + schema: + $ref: "#/components/schemas/CILogErrors" + description: Forbidden + "408": + content: + application/json: + schema: + $ref: "#/components/schemas/CILogIntakeErrors" + description: Request Timeout + "413": + content: + application/json: + schema: + $ref: "#/components/schemas/CILogIntakeErrors" + description: Payload Too Large + "429": + content: + application/json: + schema: + $ref: "#/components/schemas/CILogIntakeErrors" + description: Too Many Requests + security: + - apiKeyAuth: [] + servers: + - url: https://{subdomain}.{site} + variables: + site: + default: datadoghq.com + description: The regional site for CI Visibility customers. + enum: + - datadoghq.com + - us3.datadoghq.com + - us5.datadoghq.com + - ap1.datadoghq.com + - ap2.datadoghq.com + - uk1.datadoghq.com + - datadoghq.eu + x-enum-varnames: + - US1 + - US3 + - US5 + - AP1 + - AP2 + - UK1 + - EU1 + subdomain: + default: http-intake.logs + description: The subdomain where the API is deployed. + - url: "{protocol}://{name}" + variables: + name: + default: http-intake.logs.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: http-intake.logs + description: The subdomain where the API is deployed. + summary: Send CI job logs + tags: + - CI Visibility Logs + x-codegen-request-body-name: body /api/v2/cloud_auth/aws/persona_mapping: get: description: List all AWS cloud authentication persona mappings. This endpoint retrieves all configured persona mappings that associate AWS IAM principals with Datadog users. @@ -244478,6 +244757,8 @@ tags: [CI Visibility GitHub Actions setup page](https://docs.datadoghq.com/continuous_integration/pipelines/github/) for more information. name: CI Visibility GitHub Accounts + - description: Send CI job logs over HTTP for CI Visibility. + name: CI Visibility Logs - description: |- Search or aggregate your CI Visibility pipeline events and send them to your Datadog site over HTTP. See the [CI Pipeline Visibility in Datadog page](https://docs.datadoghq.com/continuous_integration/pipelines/) for more information. name: CI Visibility Pipelines diff --git a/examples/v2/ci-visibility-logs/SubmitCILog.ts b/examples/v2/ci-visibility-logs/SubmitCILog.ts new file mode 100644 index 000000000000..80872c97eaa6 --- /dev/null +++ b/examples/v2/ci-visibility-logs/SubmitCILog.ts @@ -0,0 +1,32 @@ +/** + * Send CI job logs returns "Request accepted for processing" response + */ + +import { client, v2 } from "@datadog/datadog-api-client"; + +const configuration = client.createConfiguration(); +const apiInstance = new v2.CIVisibilityLogsApi(configuration); + +const params: v2.CIVisibilityLogsApiSubmitCILogRequest = { + body: [ + { + ddtags: "runner:linux,architecture:amd64", + jobId: "job-456", + lineNumber: 812, + message: "Running go test ./...", + pipelineUniqueId: "3eacb6f3-ff04-4e10-8a9c-46e6d054024a", + providerName: "example-provider", + sectionName: "tests", + status: "warn", + }, + ], +}; + +apiInstance + .submitCILog(params) + .then((data: any) => { + console.log( + "API called successfully. Returned data: " + JSON.stringify(data) + ); + }) + .catch((error: any) => console.error(error)); diff --git a/examples/v2/ci-visibility-logs/SubmitCILog_1818302850.ts b/examples/v2/ci-visibility-logs/SubmitCILog_1818302850.ts new file mode 100644 index 000000000000..6cd9dacf7375 --- /dev/null +++ b/examples/v2/ci-visibility-logs/SubmitCILog_1818302850.ts @@ -0,0 +1,32 @@ +/** + * Send one CI job log returns "Request accepted for processing" response + */ + +import { client, v2 } from "@datadog/datadog-api-client"; + +const configuration = client.createConfiguration(); +const apiInstance = new v2.CIVisibilityLogsApi(configuration); + +const params: v2.CIVisibilityLogsApiSubmitCILogRequest = { + body: [ + { + message: "Running go test ./...", + pipelineUniqueId: "3eacb6f3-ff04-4e10-8a9c-46e6d054024a", + jobId: "job-456", + providerName: "example-provider", + lineNumber: 1, + status: "warn", + sectionName: "tests", + ddtags: "runner:linux,architecture:amd64", + }, + ], +}; + +apiInstance + .submitCILog(params) + .then((data: any) => { + console.log( + "API called successfully. Returned data: " + JSON.stringify(data) + ); + }) + .catch((error: any) => console.error(error)); diff --git a/examples/v2/ci-visibility-logs/SubmitCILog_4195490686.ts b/examples/v2/ci-visibility-logs/SubmitCILog_4195490686.ts new file mode 100644 index 000000000000..6cf6c9980aeb --- /dev/null +++ b/examples/v2/ci-visibility-logs/SubmitCILog_4195490686.ts @@ -0,0 +1,36 @@ +/** + * Send batched CI job logs returns "Request accepted for processing" response + */ + +import { client, v2 } from "@datadog/datadog-api-client"; + +const configuration = client.createConfiguration(); +const apiInstance = new v2.CIVisibilityLogsApi(configuration); + +const params: v2.CIVisibilityLogsApiSubmitCILogRequest = { + body: [ + { + message: "Starting tests", + pipelineUniqueId: "3eacb6f3-ff04-4e10-8a9c-46e6d054024a", + jobId: "job-456", + lineNumber: 1, + status: "notice", + sectionName: "tests", + }, + { + message: "Tests passed", + pipelineUniqueId: "3eacb6f3-ff04-4e10-8a9c-46e6d054024a", + jobId: "job-456", + lineNumber: 2, + }, + ], +}; + +apiInstance + .submitCILog(params) + .then((data: any) => { + console.log( + "API called successfully. Returned data: " + JSON.stringify(data) + ); + }) + .catch((error: any) => console.error(error)); diff --git a/features/generated-test/test-runner-data/manifest.json b/features/generated-test/test-runner-data/manifest.json index 4173266cfa15..c740c70921e3 100644 --- a/features/generated-test/test-runner-data/manifest.json +++ b/features/generated-test/test-runner-data/manifest.json @@ -3808,6 +3808,20 @@ "scenario": "Get all case types returns \"OK\" response", "version": "v2" }, + { + "feature": "CI Visibility Logs", + "feature_file": "../../v2/ci_visibility_logs.feature", + "file": "v2/ci-visibility-logs/send-batched-ci-job-logs-returns-request-accepted-for-processing-response.json", + "scenario": "Send batched CI job logs returns \"Request accepted for processing\" response", + "version": "v2" + }, + { + "feature": "CI Visibility Logs", + "feature_file": "../../v2/ci_visibility_logs.feature", + "file": "v2/ci-visibility-logs/send-one-ci-job-log-returns-request-accepted-for-processing-response.json", + "scenario": "Send one CI job log returns \"Request accepted for processing\" response", + "version": "v2" + }, { "feature": "CI Visibility Pipelines", "feature_file": "../../v2/ci_visibility_pipelines.feature", diff --git a/features/generated-test/test-runner-data/v2/ci-visibility-logs/send-batched-ci-job-logs-returns-request-accepted-for-processing-response.json b/features/generated-test/test-runner-data/v2/ci-visibility-logs/send-batched-ci-job-logs-returns-request-accepted-for-processing-response.json new file mode 100644 index 000000000000..455d085bd9a5 --- /dev/null +++ b/features/generated-test/test-runner-data/v2/ci-visibility-logs/send-batched-ci-job-logs-returns-request-accepted-for-processing-response.json @@ -0,0 +1,46 @@ +{ + "api": "CIVisibilityLogs", + "expected_status": 202, + "feature": "CI Visibility Logs", + "id": "v2/CI Visibility Logs/Send batched CI job logs returns \"Request accepted for processing\" response", + "operation_id": "SubmitCILog", + "request": { + "body": { + "schema": { + "format": null, + "items": { + "format": null, + "ref": "CILogItem", + "type": "object" + }, + "ref": "CILogRequest", + "type": "array" + }, + "source": "inline", + "value": [ + { + "job_id": "job-456", + "line_number": 1, + "message": "Starting tests", + "pipeline_unique_id": "3eacb6f3-ff04-4e10-8a9c-46e6d054024a", + "section_name": "tests", + "status": "notice" + }, + { + "job_id": "job-456", + "line_number": 2, + "message": "Tests passed", + "pipeline_unique_id": "3eacb6f3-ff04-4e10-8a9c-46e6d054024a" + } + ] + }, + "content_type": "application/json", + "method": "POST", + "pagination": false, + "parameters": [], + "path": "/api/v2/cilogs" + }, + "scenario": "Send batched CI job logs returns \"Request accepted for processing\" response", + "schema_version": 1, + "version": "v2" +} diff --git a/features/generated-test/test-runner-data/v2/ci-visibility-logs/send-one-ci-job-log-returns-request-accepted-for-processing-response.json b/features/generated-test/test-runner-data/v2/ci-visibility-logs/send-one-ci-job-log-returns-request-accepted-for-processing-response.json new file mode 100644 index 000000000000..4335aab5ffea --- /dev/null +++ b/features/generated-test/test-runner-data/v2/ci-visibility-logs/send-one-ci-job-log-returns-request-accepted-for-processing-response.json @@ -0,0 +1,42 @@ +{ + "api": "CIVisibilityLogs", + "expected_status": 202, + "feature": "CI Visibility Logs", + "id": "v2/CI Visibility Logs/Send one CI job log returns \"Request accepted for processing\" response", + "operation_id": "SubmitCILog", + "request": { + "body": { + "schema": { + "format": null, + "items": { + "format": null, + "ref": "CILogItem", + "type": "object" + }, + "ref": "CILogRequest", + "type": "array" + }, + "source": "inline", + "value": [ + { + "ddtags": "runner:linux,architecture:amd64", + "job_id": "job-456", + "line_number": 1, + "message": "Running go test ./...", + "pipeline_unique_id": "3eacb6f3-ff04-4e10-8a9c-46e6d054024a", + "provider_name": "example-provider", + "section_name": "tests", + "status": "warn" + } + ] + }, + "content_type": "application/json", + "method": "POST", + "pagination": false, + "parameters": [], + "path": "/api/v2/cilogs" + }, + "scenario": "Send one CI job log returns \"Request accepted for processing\" response", + "schema_version": 1, + "version": "v2" +} diff --git a/features/generated-test/test-server-data/manifest.json b/features/generated-test/test-server-data/manifest.json index 3eaf315d4771..6dc1a1f0bc7f 100644 --- a/features/generated-test/test-server-data/manifest.json +++ b/features/generated-test/test-server-data/manifest.json @@ -170,6 +170,11 @@ "file": "v2/authn-mappings.json", "version": "v2" }, + { + "feature": "CI Visibility Logs", + "file": "v2/ci-visibility-logs.json", + "version": "v2" + }, { "feature": "CI Visibility Pipelines", "file": "v2/ci-visibility-pipelines.json", diff --git a/features/generated-test/test-server-data/v2/ci-visibility-logs.json b/features/generated-test/test-server-data/v2/ci-visibility-logs.json new file mode 100644 index 000000000000..1268cf5baf65 --- /dev/null +++ b/features/generated-test/test-server-data/v2/ci-visibility-logs.json @@ -0,0 +1,95 @@ +{ + "feature": "CI Visibility Logs", + "recordings": [ + { + "feature": "CI Visibility Logs", + "frozen_at": "2026-10-01T13:38:29.002Z", + "interactions": [ + { + "request": { + "body": { + "type": "json", + "value": [ + { + "job_id": "job-456", + "line_number": 1, + "message": "Starting tests", + "pipeline_unique_id": "3eacb6f3-ff04-4e10-8a9c-46e6d054024a", + "section_name": "tests", + "status": "notice" + }, + { + "job_id": "job-456", + "line_number": 2, + "message": "Tests passed", + "pipeline_unique_id": "3eacb6f3-ff04-4e10-8a9c-46e6d054024a" + } + ] + }, + "content_type": "application/json", + "method": "POST", + "path": "/api/v2/cilogs", + "query": [] + }, + "response": { + "body": { + "encoding": "text", + "value": "{}" + }, + "headers": { + "content-type": "application/json" + }, + "reason": "Accepted", + "status": 202 + } + } + ], + "scenario": "Send batched CI job logs returns \"Request accepted for processing\" response", + "version": "v2" + }, + { + "feature": "CI Visibility Logs", + "frozen_at": "2026-10-01T14:45:37.327Z", + "interactions": [ + { + "request": { + "body": { + "type": "json", + "value": [ + { + "ddtags": "runner:linux,architecture:amd64", + "job_id": "job-456", + "line_number": 1, + "message": "Running go test ./...", + "pipeline_unique_id": "3eacb6f3-ff04-4e10-8a9c-46e6d054024a", + "provider_name": "example-provider", + "section_name": "tests", + "status": "warn" + } + ] + }, + "content_type": "application/json", + "method": "POST", + "path": "/api/v2/cilogs", + "query": [] + }, + "response": { + "body": { + "encoding": "text", + "value": "{}" + }, + "headers": { + "content-type": "application/json" + }, + "reason": "Accepted", + "status": 202 + } + } + ], + "scenario": "Send one CI job log returns \"Request accepted for processing\" response", + "version": "v2" + } + ], + "schema_version": 1, + "version": "v2" +} diff --git a/features/support/scenarios_model_mapping.ts b/features/support/scenarios_model_mapping.ts index b46bce900c70..c9181c378257 100644 --- a/features/support/scenarios_model_mapping.ts +++ b/features/support/scenarios_model_mapping.ts @@ -5792,6 +5792,17 @@ export const ScenariosModelMappings: {[key: string]: {[key: string]: any}} = { }, "operationResponseType": "CIAppTestEventsResponse", }, + "v2.SubmitCILog": { + "contentEncoding": { + "type": "CILogContentEncoding", + "format": "", + }, + "body": { + "type": "Array", + "format": "", + }, + "operationResponseType": "any", + }, "v2.ListAWSCloudAuthPersonaMappings": { "operationResponseType": "AWSCloudAuthPersonaMappingsResponse", }, diff --git a/features/v2/ci_visibility_logs.feature b/features/v2/ci_visibility_logs.feature new file mode 100644 index 000000000000..90b789d87ec0 --- /dev/null +++ b/features/v2/ci_visibility_logs.feature @@ -0,0 +1,44 @@ +@endpoint(ci-visibility-logs) @endpoint(ci-visibility-logs-v2) +Feature: CI Visibility Logs + Send CI job logs over HTTP for CI Visibility. + + Background: + Given a valid "apiKeyAuth" key in the system + And an instance of "CIVisibilityLogs" API + And new "SubmitCILog" request + + @generated @skip @team:ddoghq/ci-app-backend + Scenario: Send CI job logs returns "Bad Request" response + Given body with value [{"ddtags": "runner:linux,architecture:amd64", "job_id": "job-456", "line_number": 812, "message": "Running go test ./...", "pipeline_unique_id": "3eacb6f3-ff04-4e10-8a9c-46e6d054024a", "provider_name": "example-provider", "section_name": "tests", "status": "warn"}] + When the request is sent + Then the response status is 400 Bad Request + + @generated @skip @team:ddoghq/ci-app-backend + Scenario: Send CI job logs returns "Payload Too Large" response + Given body with value [{"ddtags": "runner:linux,architecture:amd64", "job_id": "job-456", "line_number": 812, "message": "Running go test ./...", "pipeline_unique_id": "3eacb6f3-ff04-4e10-8a9c-46e6d054024a", "provider_name": "example-provider", "section_name": "tests", "status": "warn"}] + When the request is sent + Then the response status is 413 Payload Too Large + + @generated @skip @team:ddoghq/ci-app-backend + Scenario: Send CI job logs returns "Request Timeout" response + Given body with value [{"ddtags": "runner:linux,architecture:amd64", "job_id": "job-456", "line_number": 812, "message": "Running go test ./...", "pipeline_unique_id": "3eacb6f3-ff04-4e10-8a9c-46e6d054024a", "provider_name": "example-provider", "section_name": "tests", "status": "warn"}] + When the request is sent + Then the response status is 408 Request Timeout + + @generated @skip @team:ddoghq/ci-app-backend + Scenario: Send CI job logs returns "Request accepted for processing" response + Given body with value [{"ddtags": "runner:linux,architecture:amd64", "job_id": "job-456", "line_number": 812, "message": "Running go test ./...", "pipeline_unique_id": "3eacb6f3-ff04-4e10-8a9c-46e6d054024a", "provider_name": "example-provider", "section_name": "tests", "status": "warn"}] + When the request is sent + Then the response status is 202 Request accepted for processing + + @team:ddoghq/ci-app-backend + Scenario: Send batched CI job logs returns "Request accepted for processing" response + Given body with value [{"message": "Starting tests", "pipeline_unique_id": "3eacb6f3-ff04-4e10-8a9c-46e6d054024a", "job_id": "job-456", "line_number": 1, "status": "notice", "section_name": "tests"}, {"message": "Tests passed", "pipeline_unique_id": "3eacb6f3-ff04-4e10-8a9c-46e6d054024a", "job_id": "job-456", "line_number": 2}] + When the request is sent + Then the response status is 202 Request accepted for processing + + @team:ddoghq/ci-app-backend + Scenario: Send one CI job log returns "Request accepted for processing" response + Given body with value [{"message": "Running go test ./...", "pipeline_unique_id": "3eacb6f3-ff04-4e10-8a9c-46e6d054024a", "job_id": "job-456", "provider_name": "example-provider", "line_number": 1, "status": "warn", "section_name": "tests", "ddtags": "runner:linux,architecture:amd64"}] + When the request is sent + Then the response status is 202 Request accepted for processing diff --git a/features/v2/undo.json b/features/v2/undo.json index c65a1e0cbcb2..6b0fafaa067a 100644 --- a/features/v2/undo.json +++ b/features/v2/undo.json @@ -1483,6 +1483,12 @@ "type": "safe" } }, + "SubmitCILog": { + "tag": "CI Visibility Logs", + "undo": { + "type": "safe" + } + }, "ListAWSCloudAuthPersonaMappings": { "tag": "Cloud Authentication", "undo": { diff --git a/packages/datadog-api-client-common/servers.ts b/packages/datadog-api-client-common/servers.ts index d0cc8734a733..05e8f7816330 100644 --- a/packages/datadog-api-client-common/servers.ts +++ b/packages/datadog-api-client-common/servers.ts @@ -163,6 +163,36 @@ export const operationServers: { subdomain: "http-intake.logs", }), ], + "v2.CIVisibilityLogsApi.submitCILog": [ + new ServerConfiguration<{ + site: + | "datadoghq.com" + | "us3.datadoghq.com" + | "us5.datadoghq.com" + | "ap1.datadoghq.com" + | "ap2.datadoghq.com" + | "uk1.datadoghq.com" + | "datadoghq.eu"; + subdomain: string; + }>("https://{subdomain}.{site}", { + site: "datadoghq.com", + subdomain: "http-intake.logs", + }), + new ServerConfiguration<{ + name: string; + protocol: string; + }>("{protocol}://{name}", { + name: "http-intake.logs.datadoghq.com", + protocol: "https", + }), + new ServerConfiguration<{ + site: string; + subdomain: string; + }>("https://{subdomain}.{site}", { + site: "datadoghq.com", + subdomain: "http-intake.logs", + }), + ], "v2.EventsApi.createEvent": [ new ServerConfiguration<{ site: diff --git a/packages/datadog-api-client-v2/apis/CIVisibilityLogsApi.ts b/packages/datadog-api-client-v2/apis/CIVisibilityLogsApi.ts new file mode 100644 index 000000000000..1a1f99fab7e1 --- /dev/null +++ b/packages/datadog-api-client-v2/apis/CIVisibilityLogsApi.ts @@ -0,0 +1,226 @@ +import { + BaseAPIRequestFactory, + RequiredError, +} from "../../datadog-api-client-common/baseapi"; +import { + Configuration, + applySecurityAuthentication, +} from "../../datadog-api-client-common/configuration"; +import { + RequestContext, + HttpMethod, + ResponseContext, +} from "../../datadog-api-client-common/http/http"; + +import { logger } from "../../../logger"; +import { ObjectSerializer } from "../models/ObjectSerializer"; +import { ApiException } from "../../datadog-api-client-common/exception"; + +import { CILogContentEncoding } from "../models/CILogContentEncoding"; +import { CILogErrors } from "../models/CILogErrors"; +import { CILogIntakeErrors } from "../models/CILogIntakeErrors"; +import { CILogItem } from "../models/CILogItem"; + +export class CIVisibilityLogsApiRequestFactory extends BaseAPIRequestFactory { + public async submitCILog( + body: Array, + contentEncoding?: CILogContentEncoding, + _options?: Configuration + ): Promise { + const _config = _options || this.configuration; + + // verify required parameter 'body' is not null or undefined + if (body === null || body === undefined) { + throw new RequiredError("body", "submitCILog"); + } + + // Path Params + const localVarPath = "/api/v2/cilogs"; + + // Make Request Context + const requestContext = _config + .getServer("v2.CIVisibilityLogsApi.submitCILog") + .makeRequestContext(localVarPath, HttpMethod.POST); + requestContext.setHeaderParam("Accept", "application/json"); + requestContext.setHttpConfig(_config.httpConfig); + + // Set IaC header + if (_config.isIaC) { + requestContext.setHeaderParam("X-Datadog-Managed-By", "iac"); + } + + // Header Params + if (contentEncoding !== undefined) { + requestContext.setHeaderParam( + "Content-Encoding", + ObjectSerializer.serialize(contentEncoding, "CILogContentEncoding", "") + ); + } + + // Body Params + const contentType = ObjectSerializer.getPreferredMediaType([ + "application/json", + ]); + requestContext.setHeaderParam("Content-Type", contentType); + const serializedBody = ObjectSerializer.stringify( + ObjectSerializer.serialize(body, "Array", ""), + contentType + ); + requestContext.setBody(serializedBody); + + // Apply auth methods + applySecurityAuthentication(_config, requestContext, ["apiKeyAuth"]); + + return requestContext; + } +} + +export class CIVisibilityLogsApiResponseProcessor { + /** + * Unwraps the actual response sent by the server from the response context and deserializes the response content + * to the expected objects + * + * @params response Response returned by the server for a request to submitCILog + * @throws ApiException if the response code was not in [200, 299] + */ + public async submitCILog(response: ResponseContext): Promise { + const contentType = ObjectSerializer.normalizeMediaType( + response.headers["content-type"] + ); + if (response.httpStatusCode === 202) { + const body: any = ObjectSerializer.deserialize( + ObjectSerializer.parse(await response.body.text(), contentType), + "any" + ) as any; + return body; + } + if ( + response.httpStatusCode === 400 || + response.httpStatusCode === 408 || + response.httpStatusCode === 413 || + response.httpStatusCode === 429 + ) { + const bodyText = ObjectSerializer.parse( + await response.body.text(), + contentType + ); + let body: CILogIntakeErrors; + try { + body = ObjectSerializer.deserialize( + bodyText, + "CILogIntakeErrors" + ) as CILogIntakeErrors; + } catch (error) { + logger.debug(`Got error deserializing error: ${error}`); + throw new ApiException( + response.httpStatusCode, + bodyText + ); + } + throw new ApiException(response.httpStatusCode, body); + } + if (response.httpStatusCode === 401 || response.httpStatusCode === 403) { + const bodyText = ObjectSerializer.parse( + await response.body.text(), + contentType + ); + let body: CILogErrors; + try { + body = ObjectSerializer.deserialize( + bodyText, + "CILogErrors" + ) as CILogErrors; + } catch (error) { + logger.debug(`Got error deserializing error: ${error}`); + throw new ApiException(response.httpStatusCode, bodyText); + } + throw new ApiException(response.httpStatusCode, body); + } + + // Work around for missing responses in specification, e.g. for petstore.yaml + if (response.httpStatusCode >= 200 && response.httpStatusCode <= 299) { + const body: any = ObjectSerializer.deserialize( + ObjectSerializer.parse(await response.body.text(), contentType), + "any", + "" + ) as any; + return body; + } + + const body = (await response.body.text()) || ""; + throw new ApiException( + response.httpStatusCode, + 'Unknown API Status Code!\nBody: "' + body + '"' + ); + } +} + +export interface CIVisibilityLogsApiSubmitCILogRequest { + /** + * CI job log line or batch in JSON format. + * @type Array + */ + body: Array; + /** + * HTTP header used to compress the JSON request body. + * @type CILogContentEncoding + */ + contentEncoding?: CILogContentEncoding; +} + +export class CIVisibilityLogsApi { + private requestFactory: CIVisibilityLogsApiRequestFactory; + private responseProcessor: CIVisibilityLogsApiResponseProcessor; + private configuration: Configuration; + + public constructor( + configuration: Configuration, + requestFactory?: CIVisibilityLogsApiRequestFactory, + responseProcessor?: CIVisibilityLogsApiResponseProcessor + ) { + this.configuration = configuration; + this.requestFactory = + requestFactory || new CIVisibilityLogsApiRequestFactory(configuration); + this.responseProcessor = + responseProcessor || new CIVisibilityLogsApiResponseProcessor(); + } + + /** + * Send log lines for a CI job over HTTP. See the [CI Visibility Pipelines + * API](https://docs.datadoghq.com/api/latest/ci-visibility-pipelines/send-pipeline-event/) for submitting the + * associated pipeline and job events. + * + * A request can contain one log object or an array of up to 1,000 log objects. The maximum uncompressed request + * body size is 5.1 MiB. + * + * You can stream log lines while a CI job runs or send them after it finishes. After you submit the completed job + * event, 20 seconds without a new log line marks the job's logs as complete. Lines sent after that may not appear. + * + * A job can have up to 128 additional attributes and 256 tags. Additional attributes are top-level fields with + * string, number, Boolean, or null values. Nested objects and arrays are rejected. Additional attributes and + * `ddtags` apply to all log lines in the job. If an additional attribute has different values on different lines, + * the first value received is used. Tags supplied on different lines are combined. A job can contain up to + * 2,000,000 log records or 1 GiB of message bytes in total. + * + * To reduce request size, send gzip-compressed JSON with the `Content-Encoding: gzip` header. Retry requests after + * a 408, 429, 500, or 503 response. + * @param param The request object + */ + public submitCILog( + param: CIVisibilityLogsApiSubmitCILogRequest, + options?: Configuration + ): Promise { + const requestContextPromise = this.requestFactory.submitCILog( + param.body, + param.contentEncoding, + options + ); + return requestContextPromise.then((requestContext) => { + return this.configuration.httpApi + .send(requestContext) + .then((responseContext) => { + return this.responseProcessor.submitCILog(responseContext); + }); + }); + } +} diff --git a/packages/datadog-api-client-v2/index.ts b/packages/datadog-api-client-v2/index.ts index b996e7097fea..6f0762e5b31e 100644 --- a/packages/datadog-api-client-v2/index.ts +++ b/packages/datadog-api-client-v2/index.ts @@ -238,6 +238,11 @@ export { CIVisibilityGitHubAccountsApi, } from "./apis/CIVisibilityGitHubAccountsApi"; +export { + CIVisibilityLogsApiSubmitCILogRequest, + CIVisibilityLogsApi, +} from "./apis/CIVisibilityLogsApi"; + export { CIVisibilityPipelinesApiAggregateCIAppPipelineEventsRequest, CIVisibilityPipelinesApiCreateCIAppPipelineEventRequest, @@ -3087,6 +3092,12 @@ export { CIAppTestsBucketResponse } from "./models/CIAppTestsBucketResponse"; export { CIAppTestsGroupBy } from "./models/CIAppTestsGroupBy"; export { CIAppTestsQueryFilter } from "./models/CIAppTestsQueryFilter"; export { CIAppWarning } from "./models/CIAppWarning"; +export { CILogAttributeValue } from "./models/CILogAttributeValue"; +export { CILogContentEncoding } from "./models/CILogContentEncoding"; +export { CILogErrors } from "./models/CILogErrors"; +export { CILogIntakeError } from "./models/CILogIntakeError"; +export { CILogIntakeErrors } from "./models/CILogIntakeErrors"; +export { CILogItem } from "./models/CILogItem"; export { CircleCIAPIKey } from "./models/CircleCIAPIKey"; export { CircleCIAPIKeyType } from "./models/CircleCIAPIKeyType"; export { CircleCIAPIKeyUpdate } from "./models/CircleCIAPIKeyUpdate"; diff --git a/packages/datadog-api-client-v2/models/CILogAttributeValue.ts b/packages/datadog-api-client-v2/models/CILogAttributeValue.ts new file mode 100644 index 000000000000..2bcd485a390b --- /dev/null +++ b/packages/datadog-api-client-v2/models/CILogAttributeValue.ts @@ -0,0 +1,13 @@ +/** + * 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 2020-Present Datadog, Inc. + */ + +import { UnparsedObject } from "../../datadog-api-client-common/util"; + +/** + * A flat additional log attribute. Objects and arrays are not accepted. + */ + +export type CILogAttributeValue = string | number | boolean | UnparsedObject; diff --git a/packages/datadog-api-client-v2/models/CILogContentEncoding.ts b/packages/datadog-api-client-v2/models/CILogContentEncoding.ts new file mode 100644 index 000000000000..9e8ea1787f6b --- /dev/null +++ b/packages/datadog-api-client-v2/models/CILogContentEncoding.ts @@ -0,0 +1,18 @@ +/** + * 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 2020-Present Datadog, Inc. + */ + +import { UnparsedObject } from "../../datadog-api-client-common/util"; + +/** + * HTTP header used to compress the JSON request body. + */ + +export type CILogContentEncoding = + | typeof IDENTITY + | typeof GZIP + | UnparsedObject; +export const IDENTITY = "identity"; +export const GZIP = "gzip"; diff --git a/packages/datadog-api-client-v2/models/CILogErrors.ts b/packages/datadog-api-client-v2/models/CILogErrors.ts new file mode 100644 index 000000000000..5464f459763e --- /dev/null +++ b/packages/datadog-api-client-v2/models/CILogErrors.ts @@ -0,0 +1,52 @@ +/** + * 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 2020-Present Datadog, Inc. + */ + +import { AttributeTypeMap } from "../../datadog-api-client-common/util"; + +/** + * Authentication and authorization errors returned by the CI logs intake API. + */ +export class CILogErrors { + /** + * Error messages. + */ + "errors"?: Array; + + /** + * A container for additional, undeclared properties. + * This is a holder for any undeclared properties as specified with + * the 'additionalProperties' keyword in the OAS document. + */ + "additionalProperties"?: { [key: string]: any }; + + /** + * @ignore + */ + "_unparsed"?: boolean; + + /** + * @ignore + */ + static readonly attributeTypeMap: AttributeTypeMap = { + errors: { + baseName: "errors", + type: "Array", + }, + additionalProperties: { + baseName: "additionalProperties", + type: "{ [key: string]: any; }", + }, + }; + + /** + * @ignore + */ + static getAttributeTypeMap(): AttributeTypeMap { + return CILogErrors.attributeTypeMap; + } + + public constructor() {} +} diff --git a/packages/datadog-api-client-v2/models/CILogIntakeError.ts b/packages/datadog-api-client-v2/models/CILogIntakeError.ts new file mode 100644 index 000000000000..4fbfe7e7b0cc --- /dev/null +++ b/packages/datadog-api-client-v2/models/CILogIntakeError.ts @@ -0,0 +1,68 @@ +/** + * 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 2020-Present Datadog, Inc. + */ + +import { AttributeTypeMap } from "../../datadog-api-client-common/util"; + +/** + * A request error returned by the CI logs intake API. + */ +export class CILogIntakeError { + /** + * Error details. + */ + "detail"?: string; + /** + * HTTP status code. + */ + "status"?: string; + /** + * Error title. + */ + "title"?: string; + + /** + * A container for additional, undeclared properties. + * This is a holder for any undeclared properties as specified with + * the 'additionalProperties' keyword in the OAS document. + */ + "additionalProperties"?: { [key: string]: any }; + + /** + * @ignore + */ + "_unparsed"?: boolean; + + /** + * @ignore + */ + static readonly attributeTypeMap: AttributeTypeMap = { + detail: { + baseName: "detail", + type: "string", + }, + status: { + baseName: "status", + type: "string", + }, + title: { + baseName: "title", + type: "string", + }, + additionalProperties: { + baseName: "additionalProperties", + type: "{ [key: string]: any; }", + }, + }; + + /** + * @ignore + */ + static getAttributeTypeMap(): AttributeTypeMap { + return CILogIntakeError.attributeTypeMap; + } + + public constructor() {} +} diff --git a/packages/datadog-api-client-v2/models/CILogIntakeErrors.ts b/packages/datadog-api-client-v2/models/CILogIntakeErrors.ts new file mode 100644 index 000000000000..494b27505a0d --- /dev/null +++ b/packages/datadog-api-client-v2/models/CILogIntakeErrors.ts @@ -0,0 +1,53 @@ +/** + * 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 2020-Present Datadog, Inc. + */ +import { CILogIntakeError } from "./CILogIntakeError"; + +import { AttributeTypeMap } from "../../datadog-api-client-common/util"; + +/** + * Request errors returned by the CI logs intake API. + */ +export class CILogIntakeErrors { + /** + * Request errors. + */ + "errors"?: Array; + + /** + * A container for additional, undeclared properties. + * This is a holder for any undeclared properties as specified with + * the 'additionalProperties' keyword in the OAS document. + */ + "additionalProperties"?: { [key: string]: any }; + + /** + * @ignore + */ + "_unparsed"?: boolean; + + /** + * @ignore + */ + static readonly attributeTypeMap: AttributeTypeMap = { + errors: { + baseName: "errors", + type: "Array", + }, + additionalProperties: { + baseName: "additionalProperties", + type: "{ [key: string]: any; }", + }, + }; + + /** + * @ignore + */ + static getAttributeTypeMap(): AttributeTypeMap { + return CILogIntakeErrors.attributeTypeMap; + } + + public constructor() {} +} diff --git a/packages/datadog-api-client-v2/models/CILogItem.ts b/packages/datadog-api-client-v2/models/CILogItem.ts new file mode 100644 index 000000000000..c1be84be26ae --- /dev/null +++ b/packages/datadog-api-client-v2/models/CILogItem.ts @@ -0,0 +1,127 @@ +/** + * 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 2020-Present Datadog, Inc. + */ +import { CILogAttributeValue } from "./CILogAttributeValue"; + +import { AttributeTypeMap } from "../../datadog-api-client-common/util"; + +/** + * A CI job log line. + */ +export class CILogItem { + /** + * Comma-separated `key:value` tags. A job can have up to 256 tags, including repeated keys. + */ + "ddtags"?: string; + /** + * The job event's `resource.id`, sent through the CI Visibility pipeline API. + */ + "jobId": string; + /** + * The line number in the job log. Use 0 or 1 for the first line. + */ + "lineNumber"?: number; + /** + * The non-empty log line message. + */ + "message": string; + /** + * The `resource.unique_id` of the pipeline event, which must also match the job event's + * `resource.pipeline_unique_id`. + */ + "pipelineUniqueId": string; + /** + * The provider name sent with the pipeline event. It defaults to `custom` when omitted and, when provided, + * must be non-empty and cannot contain a comma. + */ + "providerName"?: string; + /** + * The provider-defined section containing this log line, used to display collapsible groups of lines in the CI + * job log view. + */ + "sectionName"?: string; + /** + * The status of this log line. Any string is accepted. Datadog maps non-empty values to a standard log status. + * See [status mapping](https://docs.datadoghq.com/logs/log_configuration/processors/log_status_remapper/). + */ + "status"?: string; + /** + * The log line time in RFC 3339 format with an explicit timezone. If omitted, the intake time is used. It can + * be at most 18 hours in the past or 12 hours in the future. + */ + "timestamp"?: Date; + + /** + * A container for additional, undeclared properties. + * This is a holder for any undeclared properties as specified with + * the 'additionalProperties' keyword in the OAS document. + */ + "additionalProperties"?: { [key: string]: CILogAttributeValue }; + + /** + * @ignore + */ + "_unparsed"?: boolean; + + /** + * @ignore + */ + static readonly attributeTypeMap: AttributeTypeMap = { + ddtags: { + baseName: "ddtags", + type: "string", + }, + jobId: { + baseName: "job_id", + type: "string", + required: true, + }, + lineNumber: { + baseName: "line_number", + type: "number", + format: "int64", + }, + message: { + baseName: "message", + type: "string", + required: true, + }, + pipelineUniqueId: { + baseName: "pipeline_unique_id", + type: "string", + required: true, + }, + providerName: { + baseName: "provider_name", + type: "string", + }, + sectionName: { + baseName: "section_name", + type: "string", + }, + status: { + baseName: "status", + type: "string", + }, + timestamp: { + baseName: "timestamp", + type: "Date", + format: "date-time", + }, + additionalProperties: { + baseName: "additionalProperties", + type: "{ [key: string]: CILogAttributeValue; }", + }, + }; + + /** + * @ignore + */ + static getAttributeTypeMap(): AttributeTypeMap { + return CILogItem.attributeTypeMap; + } + + public constructor() {} +} diff --git a/packages/datadog-api-client-v2/models/ObjectSerializer.ts b/packages/datadog-api-client-v2/models/ObjectSerializer.ts index c94160e100ad..036949a50ea6 100644 --- a/packages/datadog-api-client-v2/models/ObjectSerializer.ts +++ b/packages/datadog-api-client-v2/models/ObjectSerializer.ts @@ -579,6 +579,10 @@ import { CIAppTestsBucketResponse } from "./CIAppTestsBucketResponse"; import { CIAppTestsGroupBy } from "./CIAppTestsGroupBy"; import { CIAppTestsQueryFilter } from "./CIAppTestsQueryFilter"; import { CIAppWarning } from "./CIAppWarning"; +import { CILogErrors } from "./CILogErrors"; +import { CILogIntakeError } from "./CILogIntakeError"; +import { CILogIntakeErrors } from "./CILogIntakeErrors"; +import { CILogItem } from "./CILogItem"; import { CSMAgentsMetadata } from "./CSMAgentsMetadata"; import { CVSS } from "./CVSS"; import { CalculatedField } from "./CalculatedField"; @@ -6836,6 +6840,7 @@ const enumsMap: { [key: string]: any[] } = { CIAppSortOrder: ["asc", "desc"], CIAppTestEventTypeName: ["citest"], CIAppTestLevel: ["session", "module", "suite", "test"], + CILogContentEncoding: ["identity", "gzip"], CSMAgentsType: ["datadog_agent"], CampaignStatus: ["in_progress", "not_started", "completed"], CampaignType: ["campaign"], @@ -10690,6 +10695,10 @@ const typeMap: { [index: string]: any } = { CIAppTestsGroupBy: CIAppTestsGroupBy, CIAppTestsQueryFilter: CIAppTestsQueryFilter, CIAppWarning: CIAppWarning, + CILogErrors: CILogErrors, + CILogIntakeError: CILogIntakeError, + CILogIntakeErrors: CILogIntakeErrors, + CILogItem: CILogItem, CSMAgentsMetadata: CSMAgentsMetadata, CVSS: CVSS, CalculatedField: CalculatedField, @@ -18160,6 +18169,7 @@ const oneOfMap: { [index: string]: string[] } = { "CIAppPipelineEventFinishedPipeline", "CIAppPipelineEventInProgressPipeline", ], + CILogAttributeValue: ["string", "number", "boolean"], ChangeRequestIncludedItem: [ "ChangeRequestIncludedUser", "ChangeRequestIncludedDecision",