

```json
{
  "openapi": "3.0.0",
  "tags": [
    {
      "name": "Logs",
      "description": "APIs for working with logs from the Observability platform"
    }
  ],
  "info": {
    "version": "1.0.0",
    "title": "Observability API",
    "contact": {
      "name": "Unity Support",
      "url": "https://support.unity.com/"
    },
    "description": "# Introduction\n  This document outlines the API specification for the Observability API.\n  The Observability service allows the game developers to gain insight into the internal state of UGS systems in order to quickly debug issues.\n# Concepts\n  At the moment, the Observability service only supports the storage and querying of logs. The logs are fully [OpenTelemetry](https://opentelemetry.io/) compliant.\n  Logs can be automatically instrumented by Unity services, or manually created by developers, for example in a [Cloud Code JavaScript Script](https://docs.unity.com/ugs/en-us/manual/cloud-code/manual/logging/tutorials/emit-logs). \n  The Observability API does not support ingestion through an endpoint at the movement.\n# Querying\n  You can query use the Observability API to query for logs:\n    \n  * using time ranges, both absolute (`from=2023-06-29T11:30:22.939Z`) and relative (`from=now-3h`)\n  * using offset & limit pagination  \n  * using the [filtering language](https://docs.unity.com/ugs/en-us/manual/cloud-code/manual/logging/concepts/filter-logs)\n# Rate Limits\n  The API has per project rate limiting in place, for all endpoints:\n\n  | Limit per second | Limit per hour |\n  | --- | --- |\n  | 10 | 2000 |\n"
  },
  "servers": [
    {
      "url": "https://services.api.unity.com/observability/v1"
    }
  ],
  "paths": {
    "/projects/{projectId}/environments/{environmentId}/logs": {
      "parameters": [
        {
          "$ref": "#/components/parameters/projectId"
        },
        {
          "$ref": "#/components/parameters/environmentId"
        }
      ],
      "get": {
        "tags": [
          "Logs"
        ],
        "summary": "Get Logs",
        "operationId": "getLogs",
        "description": "Fetch logs from Observability API filtered by project & environment",
        "security": [
          {
            "ServiceAccount": [
              "observability.logs.list"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/projectId"
          },
          {
            "$ref": "#/components/parameters/environmentId"
          },
          {
            "$ref": "#/components/parameters/offset"
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/from"
          },
          {
            "$ref": "#/components/parameters/to"
          },
          {
            "$ref": "#/components/parameters/serviceName"
          },
          {
            "$ref": "#/components/parameters/query"
          }
        ],
        "responses": {
          "200": {
            "description": "The logs fetched in response to the query",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/logs-response"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError.usg.v1"
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationError.usg.v1"
          },
          "403": {
            "$ref": "#/components/responses/AuthorizationError.usg.v1"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError.usg.v1"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequestsError.usg.v1"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError.usg.v1"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailableError.usg.v1"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "logs-response": {
        "title": "logs-response",
        "type": "object",
        "description": "Response from the Observability service containing logs which match the query.",
        "required": [
          "offset",
          "limit",
          "results"
        ],
        "example": {
          "offset": 0,
          "limit": 100,
          "total": 42,
          "results": [
            {
              "timestamp": "2023-09-06T10:02:24.904Z",
              "severityText": "Error",
              "severityNumber": 17,
              "body": "Hello, world!",
              "resourceAttributes": [
                {
                  "unity.projectId": "z9ed0fba-547a-3287-8bc9-2bfc101d071e",
                  "service.name": "cloud-code"
                }
              ],
              "logAttributes": [
                {
                  "log.record.uid": "7e65858d-9b46-441c-a7c2-312dc0ac6f8e",
                  "custom.attribute": "custom message"
                }
              ]
            }
          ]
        },
        "properties": {
          "offset": {
            "type": "integer",
            "description": "The offset of the returned page.",
            "example": 0
          },
          "limit": {
            "type": "integer",
            "description": "The maximum number of records that could be returned.",
            "minimum": 0,
            "maximum": 100,
            "example": 50
          },
          "total": {
            "type": "integer",
            "format": "int64",
            "description": "The total number of matching log entries. May be omitted if the count is unavailable.",
            "minimum": 0,
            "example": 243
          },
          "results": {
            "type": "array",
            "description": "The log entries returned by the query.",
            "items": {
              "$ref": "#/components/schemas/log-record"
            }
          }
        }
      },
      "log-record": {
        "title": "log-record",
        "type": "object",
        "description": "An individual log record",
        "example": {
          "timestamp": "2023-09-06T10:02:24.904Z",
          "traceId": "1234567890",
          "spanId": "1234567890",
          "severityText": "Error",
          "severityNumber": 17,
          "body": "Hello, world!",
          "resourceAttributes": [
            {
              "unity.projectId": "z9ed0fba-547a-3287-8bc9-2bfc101d071e",
              "service.name": "my-service"
            }
          ],
          "logAttributes": [
            {
              "log.record.uid": "7e65858d-9b46-441c-a7c2-312dc0ac6f8e",
              "custom.attribute": "custom message"
            }
          ]
        },
        "properties": {
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "The timestamp of the record, in RFC3339 format.",
            "example": "2023-09-06T10:02:24.904Z"
          },
          "severityText": {
            "type": "string",
            "description": "The human-readable severity text.",
            "example": "Error"
          },
          "severityNumber": {
            "type": "integer",
            "description": "The matching severity number of the severity text. Refer to [OpenTelemetry docs](https://opentelemetry.io/docs/specs/otel/logs/data-model/#field-severitynumber) for mappings.",
            "example": 17
          },
          "traceId": {
            "type": "string",
            "description": "The trace ID of the log entry.",
            "example": "1234567890"
          },
          "spanId": {
            "type": "string",
            "description": "The span ID of the log entry.",
            "example": "1234567890"
          },
          "body": {
            "type": "string",
            "description": "The log message.",
            "example": "Hello, world!"
          },
          "resourceAttributes": {
            "type": "array",
            "description": "OpenTelemetry attributes associated with the origin of the log entry.",
            "items": {
              "$ref": "#/components/schemas/attribute"
            }
          },
          "logAttributes": {
            "type": "array",
            "description": "OpenTelemetry Log Attributes associated with the particular log entry. Can contain user-defined attributes.",
            "items": {
              "$ref": "#/components/schemas/attribute"
            }
          }
        }
      },
      "attribute": {
        "title": "attribute",
        "type": "object",
        "description": "An OpenTelemetry attribute key-value pair.",
        "additionalProperties": {
          "type": "string"
        },
        "example": {
          "unity.projectId": "z9ed0fba-547a-3287-8bc9-2bfc101d071e",
          "log.record.uid": "7e65858d-9b46-441c-a7c2-312dc0ac6f8e",
          "custom.attribute": "custom message"
        }
      }
    },
    "parameters": {
      "projectId": {
        "name": "projectId",
        "in": "path",
        "description": "ID of the project.",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "environmentId": {
        "name": "environmentId",
        "in": "path",
        "description": "ID of the environment.",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "from": {
        "name": "from",
        "in": "query",
        "description": "An RFC3339 timestamp used to specify the starting timestamp of the records to return. Supports relative time ranges like `now` or `now-1h`.",
        "required": false,
        "schema": {
          "type": "string",
          "example": "2023-06-29T11:30:22.939Z"
        }
      },
      "to": {
        "name": "to",
        "in": "query",
        "description": "An RFC3339 timestamp used to specify the ending timestamp of the records to return. Supports relative time ranges like `now` or `now-1h`.",
        "required": false,
        "schema": {
          "type": "string",
          "example": "2023-06-29T11:30:22.939Z"
        }
      },
      "serviceName": {
        "name": "serviceName",
        "in": "query",
        "description": "The name(s) of the service(s) to filter logs by (OpenTelemetry resource attribute `service.name`). Can be specified multiple times to filter by more than one service.",
        "required": false,
        "style": "form",
        "explode": true,
        "schema": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "example": [
            "cloud-code",
            "triggers"
          ]
        }
      },
      "query": {
        "name": "query",
        "in": "query",
        "description": "A query string used to filter the logs. Supports the [filtering language](https://docs.unity.com/ugs/en-us/manual/cloud-code/manual/logging/concepts/filter-logs).",
        "required": false,
        "schema": {
          "type": "string",
          "example": "logAttributes.type = \"script\""
        }
      },
      "offset": {
        "name": "offset",
        "in": "query",
        "description": "The offset of the records to return.",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 0,
          "example": 45
        }
      },
      "limit": {
        "name": "limit",
        "in": "query",
        "description": "The maximum number of records to return.",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 0,
          "maximum": 100,
          "example": 50
        }
      }
    },
    "securitySchemes": {
      "ServiceAccount": {
        "type": "http",
        "scheme": "basic",
        "description": "To get started with Authentication, please visit the [Service Account Authentication section](https://services.docs.unity.com/docs/service-account-auth).\n\nFor this API, you must add the following role(s) to your service account :\n| Role Type | Role Name | Permissions |\n| --- | --- | --- |\n| Project Level Role | Observability Viewer | <ul><li>observability.logs.list</li></ul> |"
      }
    },
    "responses": {
      "ValidationError.usg.v1": {
        "description": "Bad Request",
        "content": {
          "application/problem+json": {
            "schema": {
              "type": "object",
              "properties": {
                "title": {
                  "type": "string",
                  "example": "Bad Request"
                },
                "status": {
                  "type": "integer",
                  "example": 400
                },
                "detail": {
                  "type": "string",
                  "example": "Something is wrong"
                },
                "details": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "example": {
                      "code": "ERROR_CODE_123",
                      "path": "nested.value",
                      "message": "Invalid value"
                    }
                  }
                },
                "requestId": {
                  "type": "string",
                  "format": "uuid",
                  "description": "Request correlation ID",
                  "example": "aad109f8-033f-4a24-8b77-5032eb3a6158"
                }
              }
            }
          }
        }
      },
      "AuthenticationError.usg.v1": {
        "description": "Unauthorized",
        "content": {
          "application/problem+json": {
            "schema": {
              "type": "object",
              "properties": {
                "title": {
                  "type": "string",
                  "example": "Unauthorized"
                },
                "status": {
                  "type": "integer",
                  "example": 401
                },
                "detail": {
                  "type": "string",
                  "example": "Something is wrong"
                },
                "requestId": {
                  "type": "string",
                  "format": "uuid",
                  "description": "Request correlation ID",
                  "example": "aad109f8-033f-4a24-8b77-5032eb3a6158"
                }
              }
            }
          }
        }
      },
      "AuthorizationError.usg.v1": {
        "description": "Forbidden",
        "content": {
          "application/problem+json": {
            "schema": {
              "type": "object",
              "properties": {
                "title": {
                  "type": "string",
                  "example": "Forbidden"
                },
                "status": {
                  "type": "integer",
                  "example": 403
                },
                "detail": {
                  "type": "string",
                  "example": "Something is wrong"
                },
                "requestId": {
                  "type": "string",
                  "format": "uuid",
                  "description": "Request correlation ID",
                  "example": "aad109f8-033f-4a24-8b77-5032eb3a6158"
                }
              }
            }
          }
        }
      },
      "NotFoundError.usg.v1": {
        "description": "Not Found",
        "content": {
          "application/problem+json": {
            "schema": {
              "type": "object",
              "properties": {
                "title": {
                  "type": "string",
                  "example": "Not Found"
                },
                "status": {
                  "type": "integer",
                  "example": 404
                },
                "detail": {
                  "type": "string",
                  "example": "Something is wrong"
                },
                "requestId": {
                  "type": "string",
                  "format": "uuid",
                  "description": "Request correlation ID",
                  "example": "aad109f8-033f-4a24-8b77-5032eb3a6158"
                }
              }
            }
          }
        }
      },
      "TooManyRequestsError.usg.v1": {
        "description": "Too Many Requests",
        "content": {
          "application/problem+json": {
            "schema": {
              "type": "object",
              "properties": {
                "title": {
                  "type": "string",
                  "example": "Too Many Requests"
                },
                "status": {
                  "type": "integer",
                  "example": 429
                },
                "detail": {
                  "type": "string",
                  "example": "Something is wrong"
                },
                "requestId": {
                  "type": "string",
                  "format": "uuid",
                  "description": "Request correlation ID",
                  "example": "aad109f8-033f-4a24-8b77-5032eb3a6158"
                }
              }
            }
          }
        }
      },
      "InternalServerError.usg.v1": {
        "description": "Internal Server Error",
        "content": {
          "application/problem+json": {
            "schema": {
              "type": "object",
              "properties": {
                "title": {
                  "type": "string",
                  "example": "Internal Server Error"
                },
                "status": {
                  "type": "integer",
                  "example": 500
                },
                "code": {
                  "type": "integer",
                  "example": 1
                },
                "requestId": {
                  "type": "string",
                  "format": "uuid",
                  "description": "Request correlation ID",
                  "example": "aad109f8-033f-4a24-8b77-5032eb3a6158"
                }
              }
            }
          }
        }
      },
      "ServiceUnavailableError.usg.v1": {
        "description": "Service Unavailable",
        "content": {
          "application/problem+json": {
            "schema": {
              "type": "object",
              "properties": {
                "title": {
                  "type": "string",
                  "example": "Service Unavailable"
                },
                "status": {
                  "type": "integer",
                  "example": 503
                },
                "requestId": {
                  "type": "string",
                  "format": "uuid",
                  "description": "Request correlation ID",
                  "example": "aad109f8-033f-4a24-8b77-5032eb3a6158"
                }
              }
            }
          }
        }
      }
    }
  }
}
```