An ad-hoc tool to query test timing data from LUCI. Output CSV with the following columns: The "builder" column is omitted if only one builder is queried (the -builder flag).
Package output provides a flexible output generation library for Go applications. It supports multiple output formats (JSON, YAML, CSV, HTML, Markdown, etc.) with a document-builder pattern that eliminates global state and provides thread-safe operations. Package output provides a flexible document construction and rendering system for Go. The go-output v2 library is a complete redesign providing a thread-safe, immutable Document-Builder pattern to convert structured data into various output formats including JSON, YAML, CSV, HTML, console tables, Markdown, DOT graphs, Mermaid diagrams, and Draw.io files. Key features: Create a document using the builder pattern: Render to a specific format: The library supports multiple content types: Supported output formats: The v2 library introduces per-content transformations, allowing you to attach operations directly to content items at creation time: Transformations execute during rendering, allowing different tables in the same document to have different transformation logic. The library provides several built-in operations: - FilterOp: Filter records based on a predicate function - SortOp: Sort records by one or more columns - LimitOp: Limit the number of records - GroupByOp: Group records by columns with aggregation - AddColumnOp: Add calculated columns Create operations using constructor functions: Operations attached to content MUST be thread-safe and stateless: 1. Operations MUST NOT contain mutable state modified during Apply() 2. Operations MUST be safe for concurrent execution from multiple goroutines 3. Operations MUST NOT capture mutable variables in closures Example of UNSAFE operation (captures loop variable by reference): Example of SAFE operation (explicit value capture): Transformations execute lazily during document rendering: 1. Builder constructs content with attached transformations 2. Build() creates an immutable document 3. Renderer applies transformations just before output This design: - Preserves original data in the document - Supports context-aware rendering with cancellation - Enables efficient rendering with minimal memory overhead Per-content transformations have the following performance profile: - Memory overhead: O(1) per content item (slice of operation references) - Build time: O(c) where c = number of content items - Rendering time: O(c × t × r) where c = content items, t = transformations per content, r = records per table - Each operation clones content during Apply(), chained operations result in multiple clones The library is designed to handle documents with at least 100 content items, each having up to 10 transformations, with good performance. Transformations respect context cancellation: Context is checked once before each operation in the transformation chain, providing responsive cancellation without performance overhead in tight loops. The library uses fail-fast error handling - rendering stops immediately on the first transformation error: Error messages include: - Content ID and type - Operation index and name - Detailed error description A critical feature of v2 is exact key order preservation for tables: Three ways to specify key order: 1. WithKeys() - explicit key list 2. WithSchema() - full schema with field definitions 3. WithAutoSchema() - auto-detect from data (map iteration order, not recommended) The library supports multiple content types: - TableContent: Tabular data with schema-driven key ordering - TextContent: Unstructured text with styling options - RawContent: Format-specific content (HTML snippets, etc.) - SectionContent: Grouped content with hierarchical structure All content types support transformations through the WithTransformations() option. The document-level Pipeline API has been removed in v2.4.0. Use per-content transformations instead: See the migration guide (v2/docs/PIPELINE_MIGRATION.md) for detailed migration examples. 1. Use explicit WithKeys() or WithSchema() for reliable key ordering 2. Design operations to be stateless and thread-safe 3. Capture values explicitly in closures, not loop variables 4. Use context for cancellation of long-running transformations 5. Test operations with concurrent execution to verify thread safety For comprehensive best practices, see v2/BEST_PRACTICES.md.