Summary
Migrates the HyperDX API and related services from Winston to Pino for standardized,
faster, and more structured logging with improved OpenTelemetry integration.
Changes
Core Migration
- Replaced Winston with Pino across all logging infrastructure
- Upgraded @hyperdx/node-opentelemetry from v0.8.2 to v0.9.0 to support Pino
transport
- Removed deprecated dependencies:
- winston and express-winston
- @opentelemetry/host-metrics and @opentelemetry/sdk-metrics (consolidated into
newer OTel SDK)
- Added new dependencies:
- pino and pino-http for core logging
- pino-pretty for development console output
Logger Configuration (packages/api/src/utils/logger.ts)
Production:
- Outputs stringified JSON to stdout via pino/file transport
- Maintains HyperDX transport integration when API key is configured
- Includes full OpenTelemetry trace context (trace_id, span_id, trace_flags)
<img width="830" height="184" alt="Screenshot 2025-10-14 at 4 31 36 PM" src="https://github.com/user-attachments/assets/82e60919-5c4d-4688-a6f5-d54632aef749" />
Development:
- Uses pino-pretty for human-readable, colorized console output
- Hides verbose fields from console: pid, hostname, trace_id, span_id, trace_flags
- HTTP request/response objects excluded from logs via custom serializers
<img width="825" height="350" alt="image" src="https://github.com/user-attachments/assets/64b293d8-bc95-4715-931a-dbf73483d247" />
HTTP Logging:
- Replaced express-winston with pino-http
- Custom log levels based on HTTP status codes (warn for 4xx, error for 5xx+)
- Simplified log messages: HTTP {method} {url}
Error Logging Updates
Updated error logging patterns throughout the codebase to follow Pino's structured
logging conventions:
// Before (Winston)
logger.error('Error message:', error);
// After (Pino)
logger.error({ err: error }, 'Error message');
Ref: HDX-2588
This PR should also address issue: https://github.com/hyperdxio/hyperdx/issues/1035
Closes HDX-2506
`setTraceAttributes` is not working (see HDX-2599), so for now we will replace it with span attributes, to ensure that we have some way of correlating alert job logs to teams.
<img width="492" height="209" alt="Screenshot 2025-10-14 at 4 07 36 PM" src="https://github.com/user-attachments/assets/46f9391e-e4c9-4a12-bc6b-a37d53ecadf6" />
1. Improves getJSONColumnNames to support JSON type with arguments
2. Improves useRowWhere to support arrays and JSON types
How I tested this:
1. Created a new table and setup various types of formats (`JSON, JSON(max_dynamic_paths = 3, test_key String), Dynamic, Array(Tuple(test_key String, test_value Dynamic)), Map(String, Dynamic)`)
2. Reproduced exact scenario from tickt and fixed (`getJSONColumnNames`)
4. Clicked around the app with various other types, observed that `Dynamic` fields could not be clicked if they had JSON or Array formats. Fixed that (`useRowWhere`)
5. Added tests for changes, ensured existing tests worked for `Dynamuc` useRowWhere by reproducing them in app
Fixes HDX-2523
# Summary
Closes HDX-1960
This PR adds a button to our search filters component which can be used to show the _approximate_ percentage of rows which have each filter value.
https://github.com/user-attachments/assets/2dba1b28-d2b9-4414-986c-0c515d252c89
Notes:
- The percentages are based on a sample of 100k rows. The sampling is done similarly to how EE version samples logs for patterns.
- We only fetch the most common 100 values in the sample. All other values are assumed to represent <1% of the data.
- The percentages represent the distribution within the dataset after it has been filtered by the selected filters and the where clause.
- This is a potentially expensive query, even with sampling, so the percentages are only queried if they're toggled on for a particular filter, and do not refresh in live mode. They do refresh if the search or date ranges changes (outside of live mode).
Closes HDX-1887
This change allows the user to select which log and metric sources the k8s dashboard should show. Previously, the user could only select a connection, and the first log and metric source in that connection would be used.
<img width="1756" height="1121" alt="Screenshot 2025-10-07 at 2 50 34 PM" src="https://github.com/user-attachments/assets/f6e4f375-1f8d-486c-8940-4ee2ac38b94d" />
## 🤖 Installing Claude Code GitHub App
This PR adds a GitHub Actions workflow that enables Claude Code integration in our repository.
### What is Claude Code?
[Claude Code](https://claude.ai/code) is an AI coding agent that can help with:
- Bug fixes and improvements
- Documentation updates
- Implementing new features
- Code reviews and suggestions
- Writing tests
- And more!
### How it works
Once this PR is merged, we'll be able to interact with Claude by mentioning @claude in a pull request or issue comment.
Once the workflow is triggered, Claude will analyze the comment and surrounding context, and execute on the request in a GitHub action.
### Important Notes
- **This workflow won't take effect until this PR is merged**
- **@claude mentions won't work until after the merge is complete**
- The workflow runs automatically whenever Claude is mentioned in PR or issue comments
- Claude gets access to the entire PR or issue context including files, diffs, and previous comments
### Security
- Our Anthropic API key is securely stored as a GitHub Actions secret
- Only users with write access to the repository can trigger the workflow
- All Claude runs are stored in the GitHub Actions run history
- Claude's default tools are limited to reading/writing files and interacting with our repo by creating comments, branches, and commits.
- We can add more allowed tools by adding them to the workflow file like:
```
allowed_tools: Bash(npm install),Bash(npm run build),Bash(npm run lint),Bash(npm run test)
```
There's more information in the [Claude Code action repo](https://github.com/anthropics/claude-code-action).
After merging this PR, let's try mentioning @claude in a comment on any PR to get started!
Provides support for defining the ClickHouse client request timeout from a command line arg. Uses a default value of 30 seconds if the argument is not defined.
Refactors the task arg validation and parsing to leverage zod now that we have more than a few parameters.
Dynamic module resolution causes issues in builds that use tools like esbuild; resulting paths are often not the same as they would in the source tree. Instead we can simplify the loading logic to use a defined object map of names to constructor functions. The mapping object should be small enough that merge conflicts with forks should be easy to resolve.