From d56c852aa5336d29f64e6fb92d1c54c9b0875f42 Mon Sep 17 00:00:00 2001 From: MasterPtato Date: Fri, 27 Jun 2025 00:51:59 +0000 Subject: [PATCH] fix: fix logs for new actors --- .../system-test-actor/src/managerClient.ts | 2 + packages/common/fdb-util/src/lib.rs | 42 +++++------ packages/common/util/core/src/lib.rs | 4 +- packages/common/util/id/src/lib.rs | 2 +- packages/core/api/actor/src/route/logs.rs | 7 ++ .../src/ops/datacenter/get_for_label.rs | 7 +- .../cluster/src/ops/datacenter/mod.rs | 2 +- packages/edge/api/actor/src/route/actors.rs | 45 ++++++----- .../edge/infra/client/actor-kv/src/key.rs | 2 +- .../edge/infra/client/actor-kv/src/lib.rs | 2 +- .../infra/client/actor-kv/src/list_query.rs | 2 +- .../client/config/src/runner_protocol.rs | 8 +- packages/edge/infra/client/echo/src/main.rs | 20 ++++- .../infra/guard/core/src/proxy_service.rs | 6 +- .../infra/guard/core/src/request_context.rs | 5 +- packages/edge/infra/guard/server/src/tls.rs | 5 +- .../migrations/20200101000000_init.up.sql | 8 +- .../pegboard/src/ops/actor/log/read.rs | 75 +++++++++++++++++++ sdks/api/fern/definition/actors/logs.yml | 3 + sdks/api/full/go/actors/logs.go | 4 +- sdks/api/full/openapi/openapi.yml | 8 +- sdks/api/full/openapi_compat/openapi.yml | 8 +- .../rust/docs/ActorsGetActorLogsResponse.md | 1 + .../models/actors_get_actor_logs_response.rs | 5 ++ .../logs/types/GetActorLogsResponse.ts | 4 +- .../logs/types/GetActorLogsResponse.ts | 7 +- sdks/api/runtime/go/actors/logs.go | 4 +- sdks/api/runtime/openapi/openapi.yml | 8 +- sdks/api/runtime/openapi_compat/openapi.yml | 8 +- .../rust/docs/ActorsGetActorLogsResponse.md | 1 + .../models/actors_get_actor_logs_response.rs | 6 +- .../logs/types/GetActorLogsResponse.ts | 4 +- .../logs/types/GetActorLogsResponse.ts | 7 +- site/src/content/docs/cloud/api/errors.mdx | 7 ++ 34 files changed, 248 insertions(+), 81 deletions(-) diff --git a/examples/system-test-actor/src/managerClient.ts b/examples/system-test-actor/src/managerClient.ts index 8314751473..59fd298b6a 100644 --- a/examples/system-test-actor/src/managerClient.ts +++ b/examples/system-test-actor/src/managerClient.ts @@ -48,6 +48,8 @@ export function connectToManager() { }; client.write(encodeFrame(response)); + console.log(`actor_${packet.start_actor.actor_id}`, 'fweh'); + const kvMessage = { kv: { actor_id: packet.start_actor.actor_id, diff --git a/packages/common/fdb-util/src/lib.rs b/packages/common/fdb-util/src/lib.rs index 49f554c785..e27baa166f 100644 --- a/packages/common/fdb-util/src/lib.rs +++ b/packages/common/fdb-util/src/lib.rs @@ -11,12 +11,12 @@ use foundationdb::{ self as fdb, future::FdbValue, options::DatabaseOption, - tuple::{self, PackResult, PackError, TuplePack, TupleUnpack}, + tuple::{self, PackError, PackResult, TuplePack, TupleUnpack}, KeySelector, RangeOption, }; -pub mod keys; pub mod codes; +pub mod keys; mod metrics; /// Makes the code blatantly obvious if its using a snapshot read. @@ -193,34 +193,34 @@ pub fn end_of_key_range(key: &[u8]) -> Vec { // Copied from foundationdb crate #[inline] pub fn parse_bytes(input: &[u8], num: usize) -> PackResult<(&[u8], &[u8])> { - if input.len() < num { - Err(PackError::MissingBytes) - } else { - Ok((&input[num..], &input[..num])) - } + if input.len() < num { + Err(PackError::MissingBytes) + } else { + Ok((&input[num..], &input[..num])) + } } // Copied from foundationdb crate #[inline] pub fn parse_byte(input: &[u8]) -> PackResult<(&[u8], u8)> { - if input.is_empty() { - Err(PackError::MissingBytes) - } else { - Ok((&input[1..], input[0])) - } + if input.is_empty() { + Err(PackError::MissingBytes) + } else { + Ok((&input[1..], input[0])) + } } // Copied from foundationdb crate pub fn parse_code(input: &[u8], expected: u8) -> PackResult<&[u8]> { - let (input, found) = parse_byte(input)?; - if found == expected { - Ok(input) - } else { - Err(PackError::BadCode { - found, - expected: Some(expected), - }) - } + let (input, found) = parse_byte(input)?; + if found == expected { + Ok(input) + } else { + Err(PackError::BadCode { + found, + expected: Some(expected), + }) + } } pub mod prelude { diff --git a/packages/common/util/core/src/lib.rs b/packages/common/util/core/src/lib.rs index 88250951cb..f421286477 100644 --- a/packages/common/util/core/src/lib.rs +++ b/packages/common/util/core/src/lib.rs @@ -1,7 +1,7 @@ +pub use id::Id; use rand::Rng; -pub use rivet_util_macros as macros; pub use rivet_util_id as id; -pub use id::Id; +pub use rivet_util_macros as macros; use tokio::time::{Duration, Instant}; pub mod billing; diff --git a/packages/common/util/id/src/lib.rs b/packages/common/util/id/src/lib.rs index 3abef043a7..5e120437c8 100644 --- a/packages/common/util/id/src/lib.rs +++ b/packages/common/util/id/src/lib.rs @@ -242,7 +242,7 @@ impl TuplePack for Id { let mut size = 1; w.write_all(&[fdb_util::codes::ID])?; - + // IMPORTANT: While the normal bytes representation of a v0 ID doesn't include the version, we write // it here so that we can unpack without a terminating NIL. if let Id::V0(_) = self { diff --git a/packages/core/api/actor/src/route/logs.rs b/packages/core/api/actor/src/route/logs.rs index 9540dda00b..d68178f378 100644 --- a/packages/core/api/actor/src/route/logs.rs +++ b/packages/core/api/actor/src/route/logs.rs @@ -167,6 +167,11 @@ pub async fn get_logs( .iter() .map(|x| x.stream_type as i32) .collect::>(); + let mut foreigns = logs_res + .entries + .iter() + .map(|x| x.foreign) + .collect::>(); let mut actor_indices = logs_res .entries .iter() @@ -177,6 +182,7 @@ pub async fn get_logs( lines.reverse(); timestamps.reverse(); streams.reverse(); + foreigns.reverse(); actor_indices.reverse(); let watch_nts = logs_res.entries.first().map_or(before_nts, |x| x.ts); @@ -185,6 +191,7 @@ pub async fn get_logs( lines, timestamps, streams, + foreigns, actor_indices, watch: WatchResponse::new_as_model(watch_nts), }) diff --git a/packages/core/services/cluster/src/ops/datacenter/get_for_label.rs b/packages/core/services/cluster/src/ops/datacenter/get_for_label.rs index 267d107365..2997a0e5f4 100644 --- a/packages/core/services/cluster/src/ops/datacenter/get_for_label.rs +++ b/packages/core/services/cluster/src/ops/datacenter/get_for_label.rs @@ -1,7 +1,7 @@ use chirp_workflow::prelude::*; -use crate::types::Datacenter; use crate::ops::datacenter::get::DatacenterRow; +use crate::types::Datacenter; #[derive(Debug)] pub struct Input { @@ -14,7 +14,10 @@ pub struct Output { } #[operation] -pub async fn cluster_datacenter_get_for_label(ctx: &OperationCtx, input: &Input) -> GlobalResult { +pub async fn cluster_datacenter_get_for_label( + ctx: &OperationCtx, + input: &Input, +) -> GlobalResult { let datacenters = ctx .cache() .fetch_all_json("cluster.datacenters_get_for_label", input.labels.clone(), { diff --git a/packages/core/services/cluster/src/ops/datacenter/mod.rs b/packages/core/services/cluster/src/ops/datacenter/mod.rs index 1e83973ab2..92c1376d2e 100644 --- a/packages/core/services/cluster/src/ops/datacenter/mod.rs +++ b/packages/core/services/cluster/src/ops/datacenter/mod.rs @@ -1,4 +1,5 @@ pub mod get; +pub mod get_for_label; pub mod list; pub mod location_get; pub mod resolve_for_name_id; @@ -6,4 +7,3 @@ pub mod server_discovery; pub mod server_spec_get; pub mod tls_get; pub mod topology_get; -pub mod get_for_label; diff --git a/packages/edge/api/actor/src/route/actors.rs b/packages/edge/api/actor/src/route/actors.rs index 9bfdce2f2e..d12929fdfa 100644 --- a/packages/edge/api/actor/src/route/actors.rs +++ b/packages/edge/api/actor/src/route/actors.rs @@ -451,14 +451,13 @@ pub async fn destroy( if let Some(WorkflowError::WorkflowNotFound) = res.as_workflow_error() { // Try old actors - ctx - .signal(pegboard::workflows::actor::Destroy { - override_kill_timeout_ms: query.override_kill_timeout, - }) - .to_workflow::() - .tag("actor_id", actor_id) - .send() - .await?; + ctx.signal(pegboard::workflows::actor::Destroy { + override_kill_timeout_ms: query.override_kill_timeout, + }) + .to_workflow::() + .tag("actor_id", actor_id) + .send() + .await?; old_sub.next().await?; } else { @@ -514,14 +513,13 @@ pub async fn upgrade( if let Some(WorkflowError::WorkflowNotFound) = res.as_workflow_error() { // Try old actors - ctx - .signal(pegboard::workflows::actor::Upgrade { - image_id: build.build_id, - }) - .to_workflow::() - .tag("actor_id", actor_id) - .send() - .await?; + ctx.signal(pegboard::workflows::actor::Upgrade { + image_id: build.build_id, + }) + .to_workflow::() + .tag("actor_id", actor_id) + .send() + .await?; } else { res?; } @@ -635,14 +633,13 @@ pub async fn upgrade_all( if let Some(WorkflowError::WorkflowNotFound) = res.as_workflow_error() { // Try old actors - ctx - .signal(pegboard::workflows::actor::Upgrade { - image_id: build.build_id, - }) - .to_workflow::() - .tag("actor_id", actor.actor_id) - .send() - .await?; + ctx.signal(pegboard::workflows::actor::Upgrade { + image_id: build.build_id, + }) + .to_workflow::() + .tag("actor_id", actor.actor_id) + .send() + .await?; } else { res?; } diff --git a/packages/edge/infra/client/actor-kv/src/key.rs b/packages/edge/infra/client/actor-kv/src/key.rs index 1f955f51f8..44c432411f 100644 --- a/packages/edge/infra/client/actor-kv/src/key.rs +++ b/packages/edge/infra/client/actor-kv/src/key.rs @@ -1,7 +1,7 @@ use foundationdb::tuple::{ Bytes, PackResult, TupleDepth, TuplePack, TupleUnpack, VersionstampOffset, }; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; // TODO: Custom deser impl that uses arrays instead of objects? #[derive(Clone, Serialize, Deserialize)] diff --git a/packages/edge/infra/client/actor-kv/src/lib.rs b/packages/edge/infra/client/actor-kv/src/lib.rs index f6165842f3..7e8ac6dc2f 100644 --- a/packages/edge/infra/client/actor-kv/src/lib.rs +++ b/packages/edge/infra/client/actor-kv/src/lib.rs @@ -59,7 +59,7 @@ impl ActorKv { if let Some(subspace) = &*guard { return Ok(subspace.clone()); } - + tracing::info!(actor_id=?self.actor_id, "initializing actor KV"); let root = fdb::directory::DirectoryLayer::default(); diff --git a/packages/edge/infra/client/actor-kv/src/list_query.rs b/packages/edge/infra/client/actor-kv/src/list_query.rs index 20abd04e55..c214337e46 100644 --- a/packages/edge/infra/client/actor-kv/src/list_query.rs +++ b/packages/edge/infra/client/actor-kv/src/list_query.rs @@ -1,7 +1,7 @@ use anyhow::*; use foundationdb::tuple::Subspace; use indexmap::IndexMap; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use crate::{ entry::EntryBuilder, diff --git a/packages/edge/infra/client/config/src/runner_protocol.rs b/packages/edge/infra/client/config/src/runner_protocol.rs index 0750315ef0..ca6bc98dc9 100644 --- a/packages/edge/infra/client/config/src/runner_protocol.rs +++ b/packages/edge/infra/client/config/src/runner_protocol.rs @@ -1,6 +1,4 @@ -use std::{ - io::{Cursor, Write}, -}; +use std::io::{Cursor, Write}; use anyhow::*; use pegboard::protocol; @@ -109,9 +107,7 @@ pub enum KvResponseData { #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "snake_case", deny_unknown_fields)] pub enum ToActor { - StateUpdate { - state: ActorState, - }, + StateUpdate { state: ActorState }, Kv(KvRequest), } diff --git a/packages/edge/infra/client/echo/src/main.rs b/packages/edge/infra/client/echo/src/main.rs index a4a3f34055..2ad0d2c422 100644 --- a/packages/edge/infra/client/echo/src/main.rs +++ b/packages/edge/infra/client/echo/src/main.rs @@ -1,4 +1,11 @@ -use std::{env, io::{Write, Cursor}, net::SocketAddr, path::PathBuf, sync::Arc, time::Duration}; +use std::{ + env, + io::{Cursor, Write}, + net::SocketAddr, + path::PathBuf, + sync::Arc, + time::Duration, +}; use anyhow::*; use bytes::Bytes; @@ -103,7 +110,8 @@ async fn run_socket_client(socket_path: PathBuf) -> Result<()> { // Process incoming messages while let Some(frame) = read.next().await.transpose()? { - let (_, packet) = decode_frame::(&frame.freeze()).context("failed to decode frame")?; + let (_, packet) = + decode_frame::(&frame.freeze()).context("failed to decode frame")?; println!("Received packet: {packet:?}"); if let Some(packet) = packet.get("start_actor") { @@ -117,7 +125,11 @@ async fn run_socket_client(socket_path: PathBuf) -> Result<()> { }, }); - write.lock().await.send(encode_frame(&payload).context("failed to encode frame")?).await?; + write + .lock() + .await + .send(encode_frame(&payload).context("failed to encode frame")?) + .await?; } else if let Some(packet) = packet.get("signal_actor") { let payload = json!({ "actor_state_update": { @@ -148,7 +160,7 @@ fn encode_frame(payload: &T) -> Result { serde_json::to_writer(&mut cursor, payload)?; cursor.flush()?; - + Ok(buf.into()) } diff --git a/packages/edge/infra/guard/core/src/proxy_service.rs b/packages/edge/infra/guard/core/src/proxy_service.rs index 1217366614..927e31f4fc 100644 --- a/packages/edge/infra/guard/core/src/proxy_service.rs +++ b/packages/edge/infra/guard/core/src/proxy_service.rs @@ -613,7 +613,11 @@ impl ProxyState { } #[tracing::instrument(skip_all)] - async fn release_in_flight(&self, ip_addr: std::net::IpAddr, actor_id: &Option) { + async fn release_in_flight( + &self, + ip_addr: std::net::IpAddr, + actor_id: &Option, + ) { // Skip if actor_id is None (no in-flight tracking) let actor_id = match actor_id { Some(id) => *id, diff --git a/packages/edge/infra/guard/core/src/request_context.rs b/packages/edge/infra/guard/core/src/request_context.rs index d64851228f..5a14e02d9e 100644 --- a/packages/edge/infra/guard/core/src/request_context.rs +++ b/packages/edge/infra/guard/core/src/request_context.rs @@ -191,7 +191,10 @@ impl RequestContext { .clone() .unwrap_or_default(), service_response_status: self.service_response_status.unwrap_or_default(), - service_actor_id: self.service_actor_id.map(|x| x.to_string()).unwrap_or_default(), + service_actor_id: self + .service_actor_id + .map(|x| x.to_string()) + .unwrap_or_default(), service_server_id: self.service_server_id.unwrap_or_default(), }; diff --git a/packages/edge/infra/guard/server/src/tls.rs b/packages/edge/infra/guard/server/src/tls.rs index 69f6748684..b56d881b6f 100644 --- a/packages/edge/infra/guard/server/src/tls.rs +++ b/packages/edge/infra/guard/server/src/tls.rs @@ -161,7 +161,10 @@ pub async fn create_cert_resolver( ); None } - Err(e) => bail!("Failed to build dynamic hostname actor routing regex: {}", e), + Err(e) => bail!( + "Failed to build dynamic hostname actor routing regex: {}", + e + ), }; let actor_hostname_regex_static = match build_actor_hostname_and_path_regex(EndpointType::Path, guard_hostname) { diff --git a/packages/edge/services/pegboard/db/runner-log/migrations/20200101000000_init.up.sql b/packages/edge/services/pegboard/db/runner-log/migrations/20200101000000_init.up.sql index 222f78c8d2..c6ea5d9da3 100644 --- a/packages/edge/services/pegboard/db/runner-log/migrations/20200101000000_init.up.sql +++ b/packages/edge/services/pegboard/db/runner-log/migrations/20200101000000_init.up.sql @@ -3,7 +3,13 @@ CREATE TABLE IF NOT EXISTS runner_logs ( runner_id UUID, stream_type UInt8, -- pegboard::types::LogsStreamType ts DateTime64 (9), - message String + message String, + actor_id String MATERIALIZED + if( + length(extractAll(message, '\\bactor_([a-zA-Z0-9]{12,})\\b')) > 0, + extractAll(message, '\\bactor_([a-zA-Z0-9]{12,})\\b')[1], + '' + ) ) ENGINE = ReplicatedMergeTree () PARTITION BY toStartOfHour (ts) diff --git a/packages/edge/services/pegboard/src/ops/actor/log/read.rs b/packages/edge/services/pegboard/src/ops/actor/log/read.rs index 0fdf533216..f83297356d 100644 --- a/packages/edge/services/pegboard/src/ops/actor/log/read.rs +++ b/packages/edge/services/pegboard/src/ops/actor/log/read.rs @@ -40,6 +40,7 @@ pub struct LogEntry { pub ts: i64, pub message: Vec, pub stream_type: u8, + pub foreign: bool, pub actor_id: String, } @@ -84,6 +85,7 @@ pub async fn pegboard_actor_log_read(ctx: &OperationCtx, input: &Input) -> Globa ts, message, stream_type, + 0 AS foreign, actor_id as actor_id_str FROM db_pegboard_actor_log.actor_logs3 @@ -121,6 +123,57 @@ pub async fn pegboard_actor_log_read(ctx: &OperationCtx, input: &Input) -> Globa -- Use dynamic direction directly in the ORDER BY clause ORDER BY ts {order_direction} LIMIT ? + + UNION ALL + + # actors v2 + + SELECT + l.ts, + l.message, + l.stream_type, + l.actor_id != ar.actor_id AS foreign, + ar.actor_id + FROM db_pegboard_runner_log.runner_logs AS l + JOIN db_pegboard_runner.actor_runners AS ar + ON l.runner_id = ar.runner_id + WHERE + ar.actor_id IN ? + AND l.stream_type IN ? + -- Check if the log was created during the time this actor was on this runner + AND l.ts >= ar.started_at + AND (ar.finished_at IS NULL OR l.ts <= ar.finished_at) + -- Apply timestamp filtering based on query type + AND ( + ? -- is_all + OR (? AND l.ts < fromUnixTimestamp64Nano(?)) -- is_before + OR (? AND l.ts > fromUnixTimestamp64Nano(?)) -- is_after + OR (? AND ? AND + l.ts > fromUnixTimestamp64Nano(?) AND + l.ts < fromUnixTimestamp64Nano(?)) -- is_range + ) + -- Filter for actor-specific log entries using regex + AND (l.actor_id = ar.actor_id OR l.actor_id = '') + -- Search filtering with conditional logic + AND ( + NOT ? -- NOT apply_search (always true when search not applied) + OR ( + CASE + WHEN ? THEN -- enable_regex + -- Using pre-formatted regex string + match(l.message, ?) + ELSE + -- Toggle for case sensitivity without regex + CASE + WHEN ? THEN position(l.message, ?) > 0 + ELSE positionCaseInsensitive(l.message, ?) > 0 + END + END + ) + ) + -- Use dynamic direction directly in the ORDER BY clause + ORDER BY l.ts {order_direction} + LIMIT ? " ); @@ -152,6 +205,28 @@ pub async fn pegboard_actor_log_read(ctx: &OperationCtx, input: &Input) -> Globa .bind(search_text) .bind(search_text.to_lowercase()) // Limit + .bind(input.count) + // Actors v2 (duplicate bindings) + .bind(&actor_id_strings) + .bind(&stream_type_values) + // Query type parameters + .bind(is_all) + .bind(is_before) + .bind(before_nts.unwrap_or(0)) + .bind(is_after) + .bind(after_nts.unwrap_or(0)) + .bind(is_before) // First part of AND condition for range + .bind(is_after) // Second part of AND condition for range + .bind(after_nts.unwrap_or(0)) + .bind(before_nts.unwrap_or(0)) + // Search parameters + .bind(apply_search) + .bind(enable_regex) + .bind(®ex_text) + .bind(case_sensitive) + .bind(search_text) + .bind(search_text.to_lowercase()) + // Limit .bind(input.count); let entries = query_builder.fetch_all::().await?; diff --git a/sdks/api/fern/definition/actors/logs.yml b/sdks/api/fern/definition/actors/logs.yml index c01f5865c5..bea5b1d4e1 100644 --- a/sdks/api/fern/definition/actors/logs.yml +++ b/sdks/api/fern/definition/actors/logs.yml @@ -62,6 +62,9 @@ types: 0 = stdout 1 = stderr type: list + foreigns: + docs: List of flags denoting if this log is not directly from the actor. + type: list actor_indices: docs: Index of the actor that this log was for. Use this index to look the full ID in `actor_ids`. type: list diff --git a/sdks/api/full/go/actors/logs.go b/sdks/api/full/go/actors/logs.go index b4cc815bc4..a2de673b79 100644 --- a/sdks/api/full/go/actors/logs.go +++ b/sdks/api/full/go/actors/logs.go @@ -57,7 +57,7 @@ func (e *ExportActorLogsResponse) String() string { type GetActorLogsResponse struct { // List of actor IDs in these logs. The order of these correspond to the index in the log entry. - ActorIds []string `json:"actor_ids,omitempty"` + ActorIds []sdk.Id `json:"actor_ids,omitempty"` // Sorted old to new. Lines []string `json:"lines,omitempty"` // Sorted old to new. @@ -67,6 +67,8 @@ type GetActorLogsResponse struct { // 0 = stdout // 1 = stderr Streams []int `json:"streams,omitempty"` + // List of flags denoting if this log is not directly from the actor. + Foreigns []bool `json:"foreigns,omitempty"` // Index of the actor that this log was for. Use this index to look the full ID in `actor_ids`. ActorIndices []int `json:"actor_indices,omitempty"` Watch *sdk.WatchResponse `json:"watch,omitempty"` diff --git a/sdks/api/full/openapi/openapi.yml b/sdks/api/full/openapi/openapi.yml index 7c62e11bda..7131c62a0f 100644 --- a/sdks/api/full/openapi/openapi.yml +++ b/sdks/api/full/openapi/openapi.yml @@ -11152,7 +11152,7 @@ components: actor_ids: type: array items: - type: string + $ref: '#/components/schemas/Id' description: >- List of actor IDs in these logs. The order of these correspond to the index in the log entry. @@ -11175,6 +11175,11 @@ components: 0 = stdout 1 = stderr + foreigns: + type: array + items: + type: boolean + description: List of flags denoting if this log is not directly from the actor. actor_indices: type: array items: @@ -11189,6 +11194,7 @@ components: - lines - timestamps - streams + - foreigns - actor_indices - watch ActorsExportActorLogsResponse: diff --git a/sdks/api/full/openapi_compat/openapi.yml b/sdks/api/full/openapi_compat/openapi.yml index 2b3a075f09..05b9d1464f 100644 --- a/sdks/api/full/openapi_compat/openapi.yml +++ b/sdks/api/full/openapi_compat/openapi.yml @@ -11152,7 +11152,7 @@ components: actor_ids: type: array items: - type: string + $ref: '#/components/schemas/Id' description: >- List of actor IDs in these logs. The order of these correspond to the index in the log entry. @@ -11175,6 +11175,11 @@ components: 0 = stdout 1 = stderr + foreigns: + type: array + items: + type: boolean + description: List of flags denoting if this log is not directly from the actor. actor_indices: type: array items: @@ -11189,6 +11194,7 @@ components: - lines - timestamps - streams + - foreigns - actor_indices - watch ActorsExportActorLogsResponse: diff --git a/sdks/api/full/rust/docs/ActorsGetActorLogsResponse.md b/sdks/api/full/rust/docs/ActorsGetActorLogsResponse.md index fec159c3b2..36949eda08 100644 --- a/sdks/api/full/rust/docs/ActorsGetActorLogsResponse.md +++ b/sdks/api/full/rust/docs/ActorsGetActorLogsResponse.md @@ -8,6 +8,7 @@ Name | Type | Description | Notes **lines** | **Vec** | Sorted old to new. | **timestamps** | **Vec** | Sorted old to new. | **streams** | **Vec** | Streams the logs came from. 0 = stdout 1 = stderr | +**foreigns** | **Vec** | List of flags denoting if this log is not directly from the actor. | **actor_indices** | **Vec** | Index of the actor that this log was for. Use this index to look the full ID in `actor_ids`. | **watch** | [**crate::models::WatchResponse**](WatchResponse.md) | | diff --git a/sdks/api/full/rust/src/models/actors_get_actor_logs_response.rs b/sdks/api/full/rust/src/models/actors_get_actor_logs_response.rs index 4ef76c365e..de8070d041 100644 --- a/sdks/api/full/rust/src/models/actors_get_actor_logs_response.rs +++ b/sdks/api/full/rust/src/models/actors_get_actor_logs_response.rs @@ -22,6 +22,9 @@ pub struct ActorsGetActorLogsResponse { /// Streams the logs came from. 0 = stdout 1 = stderr #[serde(rename = "streams")] pub streams: Vec, + /// List of flags denoting if this log is not directly from the actor. + #[serde(rename = "foreigns")] + pub foreigns: Vec, /// Index of the actor that this log was for. Use this index to look the full ID in `actor_ids`. #[serde(rename = "actor_indices")] pub actor_indices: Vec, @@ -35,6 +38,7 @@ impl ActorsGetActorLogsResponse { lines: Vec, timestamps: Vec, streams: Vec, + foreigns: Vec, actor_indices: Vec, watch: crate::models::WatchResponse, ) -> ActorsGetActorLogsResponse { @@ -43,6 +47,7 @@ impl ActorsGetActorLogsResponse { lines, timestamps, streams, + foreigns, actor_indices, watch: Box::new(watch), } diff --git a/sdks/api/full/typescript/src/api/resources/actors/resources/logs/types/GetActorLogsResponse.ts b/sdks/api/full/typescript/src/api/resources/actors/resources/logs/types/GetActorLogsResponse.ts index abce396e64..8d6370cdfe 100644 --- a/sdks/api/full/typescript/src/api/resources/actors/resources/logs/types/GetActorLogsResponse.ts +++ b/sdks/api/full/typescript/src/api/resources/actors/resources/logs/types/GetActorLogsResponse.ts @@ -6,7 +6,7 @@ import * as Rivet from "../../../../../index"; export interface GetActorLogsResponse { /** List of actor IDs in these logs. The order of these correspond to the index in the log entry. */ - actorIds: string[]; + actorIds: Rivet.Id[]; /** Sorted old to new. */ lines: string[]; /** Sorted old to new. */ @@ -18,6 +18,8 @@ export interface GetActorLogsResponse { * 1 = stderr */ streams: number[]; + /** List of flags denoting if this log is not directly from the actor. */ + foreigns: boolean[]; /** Index of the actor that this log was for. Use this index to look the full ID in `actor_ids`. */ actorIndices: number[]; watch: Rivet.WatchResponse; diff --git a/sdks/api/full/typescript/src/serialization/resources/actors/resources/logs/types/GetActorLogsResponse.ts b/sdks/api/full/typescript/src/serialization/resources/actors/resources/logs/types/GetActorLogsResponse.ts index e1818a7d09..5e04d4b778 100644 --- a/sdks/api/full/typescript/src/serialization/resources/actors/resources/logs/types/GetActorLogsResponse.ts +++ b/sdks/api/full/typescript/src/serialization/resources/actors/resources/logs/types/GetActorLogsResponse.ts @@ -5,6 +5,7 @@ import * as serializers from "../../../../../index"; import * as Rivet from "../../../../../../api/index"; import * as core from "../../../../../../core"; +import { Id } from "../../../../common/types/Id"; import { Timestamp } from "../../../../common/types/Timestamp"; import { WatchResponse } from "../../../../common/types/WatchResponse"; @@ -12,20 +13,22 @@ export const GetActorLogsResponse: core.serialization.ObjectSchema< serializers.actors.GetActorLogsResponse.Raw, Rivet.actors.GetActorLogsResponse > = core.serialization.object({ - actorIds: core.serialization.property("actor_ids", core.serialization.list(core.serialization.string())), + actorIds: core.serialization.property("actor_ids", core.serialization.list(Id)), lines: core.serialization.list(core.serialization.string()), timestamps: core.serialization.list(Timestamp), streams: core.serialization.list(core.serialization.number()), + foreigns: core.serialization.list(core.serialization.boolean()), actorIndices: core.serialization.property("actor_indices", core.serialization.list(core.serialization.number())), watch: WatchResponse, }); export declare namespace GetActorLogsResponse { export interface Raw { - actor_ids: string[]; + actor_ids: Id.Raw[]; lines: string[]; timestamps: Timestamp.Raw[]; streams: number[]; + foreigns: boolean[]; actor_indices: number[]; watch: WatchResponse.Raw; } diff --git a/sdks/api/runtime/go/actors/logs.go b/sdks/api/runtime/go/actors/logs.go index b4cc815bc4..a2de673b79 100644 --- a/sdks/api/runtime/go/actors/logs.go +++ b/sdks/api/runtime/go/actors/logs.go @@ -57,7 +57,7 @@ func (e *ExportActorLogsResponse) String() string { type GetActorLogsResponse struct { // List of actor IDs in these logs. The order of these correspond to the index in the log entry. - ActorIds []string `json:"actor_ids,omitempty"` + ActorIds []sdk.Id `json:"actor_ids,omitempty"` // Sorted old to new. Lines []string `json:"lines,omitempty"` // Sorted old to new. @@ -67,6 +67,8 @@ type GetActorLogsResponse struct { // 0 = stdout // 1 = stderr Streams []int `json:"streams,omitempty"` + // List of flags denoting if this log is not directly from the actor. + Foreigns []bool `json:"foreigns,omitempty"` // Index of the actor that this log was for. Use this index to look the full ID in `actor_ids`. ActorIndices []int `json:"actor_indices,omitempty"` Watch *sdk.WatchResponse `json:"watch,omitempty"` diff --git a/sdks/api/runtime/openapi/openapi.yml b/sdks/api/runtime/openapi/openapi.yml index 67ce8ecb9a..1183d05020 100644 --- a/sdks/api/runtime/openapi/openapi.yml +++ b/sdks/api/runtime/openapi/openapi.yml @@ -1978,7 +1978,7 @@ components: actor_ids: type: array items: - type: string + $ref: '#/components/schemas/Id' description: >- List of actor IDs in these logs. The order of these correspond to the index in the log entry. @@ -2001,6 +2001,11 @@ components: 0 = stdout 1 = stderr + foreigns: + type: array + items: + type: boolean + description: List of flags denoting if this log is not directly from the actor. actor_indices: type: array items: @@ -2015,6 +2020,7 @@ components: - lines - timestamps - streams + - foreigns - actor_indices - watch ActorsExportActorLogsResponse: diff --git a/sdks/api/runtime/openapi_compat/openapi.yml b/sdks/api/runtime/openapi_compat/openapi.yml index 269ce1068c..5cb8c9f58f 100644 --- a/sdks/api/runtime/openapi_compat/openapi.yml +++ b/sdks/api/runtime/openapi_compat/openapi.yml @@ -1978,7 +1978,7 @@ components: actor_ids: type: array items: - type: string + $ref: '#/components/schemas/Id' description: >- List of actor IDs in these logs. The order of these correspond to the index in the log entry. @@ -2001,6 +2001,11 @@ components: 0 = stdout 1 = stderr + foreigns: + type: array + items: + type: boolean + description: List of flags denoting if this log is not directly from the actor. actor_indices: type: array items: @@ -2015,6 +2020,7 @@ components: - lines - timestamps - streams + - foreigns - actor_indices - watch ActorsExportActorLogsResponse: diff --git a/sdks/api/runtime/rust/docs/ActorsGetActorLogsResponse.md b/sdks/api/runtime/rust/docs/ActorsGetActorLogsResponse.md index fec159c3b2..36949eda08 100644 --- a/sdks/api/runtime/rust/docs/ActorsGetActorLogsResponse.md +++ b/sdks/api/runtime/rust/docs/ActorsGetActorLogsResponse.md @@ -8,6 +8,7 @@ Name | Type | Description | Notes **lines** | **Vec** | Sorted old to new. | **timestamps** | **Vec** | Sorted old to new. | **streams** | **Vec** | Streams the logs came from. 0 = stdout 1 = stderr | +**foreigns** | **Vec** | List of flags denoting if this log is not directly from the actor. | **actor_indices** | **Vec** | Index of the actor that this log was for. Use this index to look the full ID in `actor_ids`. | **watch** | [**crate::models::WatchResponse**](WatchResponse.md) | | diff --git a/sdks/api/runtime/rust/src/models/actors_get_actor_logs_response.rs b/sdks/api/runtime/rust/src/models/actors_get_actor_logs_response.rs index e4ace83b0f..6e60422dc7 100644 --- a/sdks/api/runtime/rust/src/models/actors_get_actor_logs_response.rs +++ b/sdks/api/runtime/rust/src/models/actors_get_actor_logs_response.rs @@ -25,6 +25,9 @@ pub struct ActorsGetActorLogsResponse { /// Streams the logs came from. 0 = stdout 1 = stderr #[serde(rename = "streams")] pub streams: Vec, + /// List of flags denoting if this log is not directly from the actor. + #[serde(rename = "foreigns")] + pub foreigns: Vec, /// Index of the actor that this log was for. Use this index to look the full ID in `actor_ids`. #[serde(rename = "actor_indices")] pub actor_indices: Vec, @@ -33,12 +36,13 @@ pub struct ActorsGetActorLogsResponse { } impl ActorsGetActorLogsResponse { - pub fn new(actor_ids: Vec, lines: Vec, timestamps: Vec, streams: Vec, actor_indices: Vec, watch: crate::models::WatchResponse) -> ActorsGetActorLogsResponse { + pub fn new(actor_ids: Vec, lines: Vec, timestamps: Vec, streams: Vec, foreigns: Vec, actor_indices: Vec, watch: crate::models::WatchResponse) -> ActorsGetActorLogsResponse { ActorsGetActorLogsResponse { actor_ids, lines, timestamps, streams, + foreigns, actor_indices, watch: Box::new(watch), } diff --git a/sdks/api/runtime/typescript/src/api/resources/actors/resources/logs/types/GetActorLogsResponse.ts b/sdks/api/runtime/typescript/src/api/resources/actors/resources/logs/types/GetActorLogsResponse.ts index abce396e64..8d6370cdfe 100644 --- a/sdks/api/runtime/typescript/src/api/resources/actors/resources/logs/types/GetActorLogsResponse.ts +++ b/sdks/api/runtime/typescript/src/api/resources/actors/resources/logs/types/GetActorLogsResponse.ts @@ -6,7 +6,7 @@ import * as Rivet from "../../../../../index"; export interface GetActorLogsResponse { /** List of actor IDs in these logs. The order of these correspond to the index in the log entry. */ - actorIds: string[]; + actorIds: Rivet.Id[]; /** Sorted old to new. */ lines: string[]; /** Sorted old to new. */ @@ -18,6 +18,8 @@ export interface GetActorLogsResponse { * 1 = stderr */ streams: number[]; + /** List of flags denoting if this log is not directly from the actor. */ + foreigns: boolean[]; /** Index of the actor that this log was for. Use this index to look the full ID in `actor_ids`. */ actorIndices: number[]; watch: Rivet.WatchResponse; diff --git a/sdks/api/runtime/typescript/src/serialization/resources/actors/resources/logs/types/GetActorLogsResponse.ts b/sdks/api/runtime/typescript/src/serialization/resources/actors/resources/logs/types/GetActorLogsResponse.ts index e1818a7d09..5e04d4b778 100644 --- a/sdks/api/runtime/typescript/src/serialization/resources/actors/resources/logs/types/GetActorLogsResponse.ts +++ b/sdks/api/runtime/typescript/src/serialization/resources/actors/resources/logs/types/GetActorLogsResponse.ts @@ -5,6 +5,7 @@ import * as serializers from "../../../../../index"; import * as Rivet from "../../../../../../api/index"; import * as core from "../../../../../../core"; +import { Id } from "../../../../common/types/Id"; import { Timestamp } from "../../../../common/types/Timestamp"; import { WatchResponse } from "../../../../common/types/WatchResponse"; @@ -12,20 +13,22 @@ export const GetActorLogsResponse: core.serialization.ObjectSchema< serializers.actors.GetActorLogsResponse.Raw, Rivet.actors.GetActorLogsResponse > = core.serialization.object({ - actorIds: core.serialization.property("actor_ids", core.serialization.list(core.serialization.string())), + actorIds: core.serialization.property("actor_ids", core.serialization.list(Id)), lines: core.serialization.list(core.serialization.string()), timestamps: core.serialization.list(Timestamp), streams: core.serialization.list(core.serialization.number()), + foreigns: core.serialization.list(core.serialization.boolean()), actorIndices: core.serialization.property("actor_indices", core.serialization.list(core.serialization.number())), watch: WatchResponse, }); export declare namespace GetActorLogsResponse { export interface Raw { - actor_ids: string[]; + actor_ids: Id.Raw[]; lines: string[]; timestamps: Timestamp.Raw[]; streams: number[]; + foreigns: boolean[]; actor_indices: number[]; watch: WatchResponse.Raw; } diff --git a/site/src/content/docs/cloud/api/errors.mdx b/site/src/content/docs/cloud/api/errors.mdx index 5d841ff9b1..10d371805a 100644 --- a/site/src/content/docs/cloud/api/errors.mdx +++ b/site/src/content/docs/cloud/api/errors.mdx @@ -184,6 +184,13 @@ The prefix, `"Bearer "`, is required. Billing is not enabled. +## Build Invalid + +{`BUILD_INVALID`} + +Build configuration is invalid. + + ## Build Not Found {`BUILD_NOT_FOUND`}