45565b2c01
Dedicated host-scoped table for pushed container log lines (one row per line), chained after docker_008. host_id FK CASCADE; twin indexes — (host_id, container_name, ts) for the viewer, ts alone for the age-cutoff prune — mirroring docker_events. Integration schema-shape test asserts columns + both indexes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CAGR73DUowdVFVvYzLXC5C
49 lines
2.1 KiB
Python
49 lines
2.1 KiB
Python
"""Docker container logs table
|
|
|
|
Adds docker_logs — one row per container log line, pushed by the host agent and
|
|
folded into its metrics push. Time-series, host-scoped (container names are only
|
|
unique within a host). Bounded by a per-container size+age ring in retention, so
|
|
a chatty container keeps a shorter window rather than growing without limit.
|
|
Additive create_table + twin indexes (viewer lookup by (host, container, ts);
|
|
age-cutoff prune by ts).
|
|
|
|
Revision ID: docker_009_container_logs
|
|
Revises: docker_008_bigint_mem
|
|
Create Date: 2026-07-19
|
|
"""
|
|
from typing import Sequence, Union
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
revision: str = "docker_009_container_logs"
|
|
down_revision: Union[str, None] = "docker_008_bigint_mem"
|
|
branch_labels: Union[str, Sequence[str], None] = None
|
|
depends_on: Union[str, Sequence[str], None] = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.create_table(
|
|
"docker_logs",
|
|
sa.Column("id", sa.String(length=36), nullable=False),
|
|
sa.Column("host_id", sa.String(length=36), nullable=False),
|
|
sa.Column("container_name", sa.String(length=255), nullable=False),
|
|
sa.Column("ts", sa.DateTime(timezone=True), nullable=False),
|
|
sa.Column("stream", sa.String(length=8), nullable=False, server_default="stdout"),
|
|
sa.Column("line", sa.Text(), nullable=False, server_default=""),
|
|
sa.ForeignKeyConstraint(["host_id"], ["hosts.id"], ondelete="CASCADE"),
|
|
sa.PrimaryKeyConstraint("id"),
|
|
)
|
|
op.create_index("ix_docker_logs_host_id", "docker_logs", ["host_id"])
|
|
op.create_index("ix_docker_logs_container_name", "docker_logs", ["container_name"])
|
|
op.create_index("ix_docker_logs_host_container_time",
|
|
"docker_logs", ["host_id", "container_name", "ts"])
|
|
op.create_index("ix_docker_logs_ts", "docker_logs", ["ts"])
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_index("ix_docker_logs_ts", table_name="docker_logs")
|
|
op.drop_index("ix_docker_logs_host_container_time", table_name="docker_logs")
|
|
op.drop_index("ix_docker_logs_container_name", table_name="docker_logs")
|
|
op.drop_index("ix_docker_logs_host_id", table_name="docker_logs")
|
|
op.drop_table("docker_logs")
|