Tilebox stores logs and spans for each workflow job. Use the jobs client to query that telemetry from notebooks, scripts, or automated diagnostics.
Query job logs
Section titled “Query job logs”query_logs() returns a LogRecords list. Pagination is handled automatically.
from tilebox.workflows import Client
client = Client()job = client.jobs().find("019e07b1-916b-0630-f3ba-f1c33235d174")
logs = client.jobs().query_logs(job)
for record in logs: print(record.time, record.severity_text, record.body) print(record.attributes)package main
import ( "context" "fmt" "log/slog" "time"
"github.com/google/uuid" "github.com/tilebox/tilebox-go/workflows/v1")
func main() { ctx := context.Background() client := workflows.NewClient() jobID := uuid.MustParse("019e07b1-916b-0630-f3ba-f1c33235d174")
for record, err := range client.Jobs.QueryLogs( ctx, jobID, workflows.WithSortDirection(workflows.Ascending), ) { if err != nil { slog.ErrorContext(ctx, "failed to query job logs", slog.Any("error", err)) return }
fmt.Println(record.Time.Format(time.RFC3339Nano), record.Level, record.Body) fmt.Println(record.Attributes) }}Each log record includes:
timeseverity_numberandseverity_textbodytrace_idandspan_idattributesrunner_attributes
As pandas DataFrame
Section titled “As pandas DataFrame”Use to_pandas() to convert log records to a pandas DataFrame.
logs_df = client.jobs().query_logs(job).to_pandas()logs_df[["time", "severity_text", "body"]]
Query job spans
Section titled “Query job spans”query_spans() returns a Spans list. Pagination is handled automatically.
spans = client.jobs().query_spans(job.id)
for span in spans: print(span.name, span.status_code, span.duration) print(span.attributes)package main
import ( "context" "fmt" "log/slog"
"github.com/google/uuid" "github.com/tilebox/tilebox-go/workflows/v1")
func main() { ctx := context.Background() client := workflows.NewClient() jobID := uuid.MustParse("019e07b1-916b-0630-f3ba-f1c33235d174")
for span, err := range client.Jobs.QuerySpans( ctx, jobID, workflows.WithSortDirection(workflows.Ascending), ) { if err != nil { slog.ErrorContext(ctx, "failed to query job spans", slog.Any("error", err)) return }
fmt.Println(span.Name, span.StatusCode, span.Duration()) fmt.Println(span.Attributes) }}Each span includes:
start_timeandend_timedurationtrace_id,span_id, andparent_span_idnamestatus_codeandstatus_messageattributesrunner_attributesevents
As pandas DataFrame
Section titled “As pandas DataFrame”Use to_pandas() to convert spans to a pandas DataFrame.
spans_df = client.jobs().query_spans(job).to_pandas()
slow_spans = spans_df.sort_values("duration", ascending=False).head(10)slow_spans[["name", "duration", "start_time"]]
Nested attributes, runner_attributes, and events stay as Python objects in DataFrame columns. Span DataFrames include a computed duration column.