Compare commits

...

2 Commits

Author SHA1 Message Date
Tushar Vats
e78240c2bb feat: added for promql as well 2026-05-12 15:16:51 +05:30
Tushar Vats
3aa69446ed feat: add query length validation 2026-05-12 14:51:37 +05:30
3 changed files with 75 additions and 14 deletions

View File

@@ -1,5 +1,7 @@
package querybuildertypesv5
import "github.com/SigNoz/signoz/pkg/errors"
type ClickHouseQuery struct {
// name of the query
Name string `json:"name"`
@@ -15,3 +17,21 @@ type ClickHouseQuery struct {
func (q ClickHouseQuery) Copy() ClickHouseQuery {
return q
}
// Validate performs preliminary validation on ClickHouseQuery.
func (q ClickHouseQuery) Validate() error {
if q.Query == "" {
return errors.NewInvalidInputf(
errors.CodeInvalidInput,
"ClickHouse SQL query is required",
)
}
if len(q.Query) > MaxClickHouseQueryLength {
return errors.NewInvalidInputf(
errors.CodeInvalidInput,
"ClickHouse SQL query exceeds maximum allowed length of %d characters",
MaxClickHouseQueryLength,
)
}
return nil
}

View File

@@ -1,5 +1,7 @@
package querybuildertypesv5
import "github.com/SigNoz/signoz/pkg/errors"
type PromQuery struct {
// name of the query
Name string `json:"name"`
@@ -19,3 +21,21 @@ type PromQuery struct {
func (q PromQuery) Copy() PromQuery {
return q // shallow copy is sufficient
}
// Validate performs preliminary validation on PromQuery.
func (q PromQuery) Validate() error {
if q.Query == "" {
return errors.NewInvalidInputf(
errors.CodeInvalidInput,
"PromQL query is required",
)
}
if len(q.Query) > MaxPromQLQueryLength {
return errors.NewInvalidInputf(
errors.CodeInvalidInput,
"PromQL query exceeds maximum allowed length of %d characters",
MaxPromQLQueryLength,
)
}
return nil
}

View File

@@ -10,6 +10,21 @@ import (
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
)
const (
// MaxFilterExpressionLength bounds a builder filter expression. The compiled SQL
// adds wrapper syntax on top of this, so we stay well below ClickHouse's parser
// limit (max_query_size, 262144 bytes by default) to leave room for that overhead.
MaxFilterExpressionLength = 250_000
// MaxClickHouseQueryLength bounds a raw ClickHouse SQL query. ClickHouse's
// default max_query_size is 262144 bytes; we leave a small headroom for any
// wrapping (CTEs, time filters, etc.) the server adds before sending.
MaxClickHouseQueryLength = 260_000
// MaxPromQLQueryLength bounds a raw PromQL query string. Picked to match the
// other query bounds; PromQL has no equivalent server-side parser cap, but we
// reject pathologically large inputs to protect the server.
MaxPromQLQueryLength = 260_000
)
// getQueryIdentifier returns a friendly identifier for a query based on its type and name/content.
func getQueryIdentifier(envelope QueryEnvelope, index int) string {
name := envelope.GetQueryName()
@@ -147,6 +162,10 @@ func (q *QueryBuilderQuery[T]) Validate(opts ...ValidationOption) error {
return err
}
if err := q.validateFilterExpression(); err != nil {
return err
}
return nil
}
@@ -352,6 +371,20 @@ func (q *QueryBuilderQuery[T]) validateFunctions() error {
return nil
}
func (q *QueryBuilderQuery[T]) validateFilterExpression() error {
if q.Filter == nil || q.Filter.Expression == "" {
return nil
}
if len(q.Filter.Expression) > MaxFilterExpressionLength {
return errors.NewInvalidInputf(
errors.CodeInvalidInput,
"filter expression exceeds maximum allowed length of %d characters",
MaxFilterExpressionLength,
)
}
return nil
}
func (q *QueryBuilderQuery[T]) validateSecondaryAggregations() error {
for i, secAgg := range q.SecondaryAggregations {
// Secondary aggregation expression can be empty - we allow it per requirements
@@ -630,13 +663,7 @@ func validateQueryEnvelope(envelope QueryEnvelope, opts ...ValidationOption) err
"invalid PromQL spec",
)
}
if spec.Query == "" {
return errors.NewInvalidInputf(
errors.CodeInvalidInput,
"PromQL query is required",
)
}
return nil
return spec.Validate()
case QueryTypeClickHouseSQL:
spec, ok := envelope.Spec.(ClickHouseQuery)
if !ok {
@@ -645,13 +672,7 @@ func validateQueryEnvelope(envelope QueryEnvelope, opts ...ValidationOption) err
"invalid ClickHouse SQL spec",
)
}
if spec.Query == "" {
return errors.NewInvalidInputf(
errors.CodeInvalidInput,
"ClickHouse SQL query is required",
)
}
return nil
return spec.Validate()
default:
return errors.NewInvalidInputf(
errors.CodeInvalidInput,