Compare commits

...

4 Commits

Author SHA1 Message Date
Vinícius Lourenço
dfcaf70f00 feat(tsgo): use tsgo to type-check 2026-04-29 21:24:15 -03:00
primus-bot[bot]
b71de5b561 chore(release): bump to v0.121.0 (#11139)
Some checks failed
build-staging / prepare (push) Has been cancelled
build-staging / js-build (push) Has been cancelled
build-staging / go-build (push) Has been cancelled
build-staging / staging (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
Co-authored-by: primus-bot[bot] <171087277+primus-bot[bot]@users.noreply.github.com>
2026-04-29 16:08:15 +00:00
Piyush Singariya
a672335a33 fix: Body Search warning with FTS in JSON Logs (#10807)
Some checks failed
build-staging / prepare (push) Has been cancelled
build-staging / js-build (push) Has been cancelled
build-staging / go-build (push) Has been cancelled
build-staging / staging (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
* fix: fts warning miss in direct text search

* fix: comments

* test: added one more test variation

* ci: go lint

* fix: fts warning update

* fix: integration tests

* fix: go test and fmtlint
2026-04-29 08:50:28 +00:00
Abhi kumar
f4e5534e53 chore: updated drilldown popup ui to match tooltip (#11113) 2026-04-29 06:55:01 +00:00
16 changed files with 141 additions and 113 deletions

View File

@@ -190,7 +190,7 @@ services:
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
signoz:
!!merge <<: *db-depend
image: signoz/signoz:v0.120.0
image: signoz/signoz:v0.121.0
ports:
- "8080:8080" # signoz port
# - "6060:6060" # pprof port

View File

@@ -117,7 +117,7 @@ services:
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
signoz:
!!merge <<: *db-depend
image: signoz/signoz:v0.120.0
image: signoz/signoz:v0.121.0
ports:
- "8080:8080" # signoz port
volumes:

View File

@@ -181,7 +181,7 @@ services:
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
signoz:
!!merge <<: *db-depend
image: signoz/signoz:${VERSION:-v0.120.0}
image: signoz/signoz:${VERSION:-v0.121.0}
container_name: signoz
ports:
- "8080:8080" # signoz port

View File

@@ -109,7 +109,7 @@ services:
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
signoz:
!!merge <<: *db-depend
image: signoz/signoz:${VERSION:-v0.120.0}
image: signoz/signoz:${VERSION:-v0.121.0}
container_name: signoz
ports:
- "8080:8080" # signoz port

View File

@@ -198,6 +198,7 @@
"@types/redux-mock-store": "1.0.4",
"@types/styled-components": "^5.1.4",
"@types/uuid": "^8.3.1",
"@typescript/native-preview": "7.0.0-dev.20260421.2",
"autoprefixer": "10.4.19",
"babel-plugin-styled-components": "^1.12.0",
"eslint-plugin-sonarjs": "4.0.2",
@@ -240,7 +241,7 @@
"*.(js|jsx|ts|tsx)": [
"oxlint --fix",
"oxfmt --write",
"sh scripts/typecheck-staged.sh"
"tsgo --noEmit"
],
"*.(scss|css)": [
"stylelint"
@@ -266,4 +267,4 @@
"tmp": "0.2.4",
"vite": "npm:rolldown-vite@7.3.1"
}
}
}

View File

@@ -1,25 +0,0 @@
files="";
# lint-staged will pass all files in $1 $2 $3 etc. iterate and concat.
for var in "$@"
do
files="$files \"$var\","
done
# create temporary tsconfig which includes only passed files
str="{
\"extends\": \"./tsconfig.json\",
\"include\": [ \"src/typings/**/*.ts\",\"src/**/*.d.ts\", \"./babel.config.js\", \"./jest.config.ts\", \"./.eslintrc.js\",\"./__mocks__\",\"./public\",\"./tests\",\"./commitlint.config.ts\",\"./webpack.config.js\",\"./webpack.config.prod.js\",\"./jest.setup.ts\",\"./**/*.d.ts\",$files]
}"
echo $str > tsconfig.tmp
# run typecheck using temp config
tsc -p ./tsconfig.tmp
# capture exit code of tsc
code=$?
# delete temp config
rm ./tsconfig.tmp
exit $code

View File

@@ -104,7 +104,12 @@ export const usePanelContextMenu = ({
}
if (data && data?.record?.queryName) {
onClick(data.coord, { ...data.record, label: data.label, timeRange });
onClick(data.coord, {
...data.record,
label: data.label,
seriesColor: data.seriesColor,
timeRange,
});
}
},
[onClick, queryResponse],

View File

@@ -196,6 +196,7 @@ export const getUplotClickData = ({
coord: { x: number; y: number };
record: { queryName: string; filters: FilterData[] };
label: string | React.ReactNode;
seriesColor?: string;
} | null => {
if (!queryData?.queryName || !metric) {
return null;
@@ -208,6 +209,8 @@ export const getUplotClickData = ({
// Generate label from focusedSeries data
let label: string | React.ReactNode = '';
const seriesColor = focusedSeries?.color;
if (focusedSeries && focusedSeries.seriesName) {
label = (
<span style={{ color: focusedSeries.color }}>
@@ -223,6 +226,7 @@ export const getUplotClickData = ({
},
record,
label,
seriesColor,
};
};
@@ -237,6 +241,7 @@ export const getPieChartClickData = (
queryName: string;
filters: FilterData[];
label: string | React.ReactNode;
seriesColor?: string;
} | null => {
const { metric, queryName } = arc.data.record;
if (!queryName || !metric) {
@@ -248,6 +253,7 @@ export const getPieChartClickData = (
queryName,
filters: getFiltersFromMetric(metric), // TODO: add where clause query as well.
label,
seriesColor: arc.data.color,
};
};

View File

@@ -22,6 +22,7 @@ export interface AggregateData {
endTime: number;
};
label?: string | React.ReactNode;
seriesColor?: string;
}
const useAggregateDrilldown = ({

View File

@@ -228,7 +228,13 @@ const useBaseAggregateOptions = ({
return (
<ContextMenu.Item
key={key}
icon={isLoading ? <LoadingOutlined spin /> : icon}
icon={
isLoading ? (
<LoadingOutlined spin />
) : (
<span style={{ color: aggregateData?.seriesColor }}>{icon}</span>
)
}
onClick={(): void => onClick()}
disabled={isLoading}
>

View File

@@ -4,7 +4,7 @@
gap: 8px;
padding: 8px;
cursor: pointer;
color: var(--foreground);
color: var(--muted-foreground);
font-family: Inter;
font-size: var(--font-size-sm);
font-weight: 600;
@@ -20,13 +20,10 @@
overflow: hidden;
text-overflow: ellipsis;
&:hover {
background-color: var(--l1-background);
}
&:hover,
&:focus {
outline: none;
background-color: var(--l1-background);
background-color: var(--l2-background-hover);
}
&.disabled {
@@ -47,7 +44,8 @@
}
&:hover {
background-color: var(--bg-cherry-100);
background-color: var(--danger-background);
color: var(--l1-foreground);
}
}
@@ -74,73 +72,24 @@
}
.context-menu-header {
padding-bottom: 4px;
border-bottom: 1px solid var(--l1-border);
padding: 8px 12px;
border-bottom: 1px solid var(--l2-border);
color: var(--muted-foreground);
}
// Target the popover inner specifically for context menu
.context-menu .ant-popover-inner {
padding: 12px 8px !important;
// max-height: 254px !important;
max-width: 300px !important;
padding: 0;
border-radius: 6px;
max-width: 300px;
background: var(--l2-background) !important;
border: 1px solid var(--l2-border) !important;
}
// Dark mode support
.darkMode {
.context-menu-item {
color: var(--muted-foreground);
&:hover,
&:focus {
background-color: var(--l2-background);
}
&.danger {
color: var(--bg-cherry-400);
.icon {
color: var(--bg-cherry-400);
}
&:hover {
background-color: var(--danger-background);
color: var(--l1-foreground);
}
}
.icon {
color: var(--bg-robin-400);
}
}
.context-menu-header {
border-bottom: 1px solid var(--l1-border);
color: var(--muted-foreground);
}
// Set the menu popover background
.context-menu .ant-popover-inner {
background: var(--l1-background) !important;
border: 1px solid var(--border) !important;
}
}
// Context menu backdrop overlay
.context-menu-backdrop {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
inset: 0;
z-index: 9999;
background: transparent;
cursor: default;
// Prevent any pointer events from reaching elements behind
pointer-events: auto;
// Ensure it covers the entire viewport including any scrollable areas
position: fixed !important;
inset: 0;
}

View File

@@ -6697,6 +6697,54 @@
dependencies:
"@types/yargs-parser" "*"
"@typescript/native-preview-darwin-arm64@7.0.0-dev.20260421.2":
version "7.0.0-dev.20260421.2"
resolved "https://registry.yarnpkg.com/@typescript/native-preview-darwin-arm64/-/native-preview-darwin-arm64-7.0.0-dev.20260421.2.tgz#8d2a1a9febf3759dcaddc6d5731874f4df01f003"
integrity sha512-fHv1r3ZmVo6zxuAIFmuX3w9QxbcauoG0SsWhmDwm6VmRubLlOJIcmTtlmV3JAb9oOnq8LuzZljzT7Q39fSMQDw==
"@typescript/native-preview-darwin-x64@7.0.0-dev.20260421.2":
version "7.0.0-dev.20260421.2"
resolved "https://registry.yarnpkg.com/@typescript/native-preview-darwin-x64/-/native-preview-darwin-x64-7.0.0-dev.20260421.2.tgz#1f878dedaf60505d7b67505dbe47b44503593e09"
integrity sha512-KWTR6xbW9t+JS7D5DQIzo75pqVXVWUxF9PMv/+S6xsnOjCVd6g0ixHcFpFMJMKSUQpGPr8Z5f7b8ks6LHW01jg==
"@typescript/native-preview-linux-arm64@7.0.0-dev.20260421.2":
version "7.0.0-dev.20260421.2"
resolved "https://registry.yarnpkg.com/@typescript/native-preview-linux-arm64/-/native-preview-linux-arm64-7.0.0-dev.20260421.2.tgz#529465d6436de4ee0ed922d7de2e91fb605d7622"
integrity sha512-VLMEuml3BhUb+jaL0TXQ4xvVODxJF+RhkI+tBWvlynsJI4khTXEiwWh+wPOJrsfBRYFRMXEu28Odl/HXkYze8w==
"@typescript/native-preview-linux-arm@7.0.0-dev.20260421.2":
version "7.0.0-dev.20260421.2"
resolved "https://registry.yarnpkg.com/@typescript/native-preview-linux-arm/-/native-preview-linux-arm-7.0.0-dev.20260421.2.tgz#cb5abde3e2fed1ed1c1aff1f22338a4f4c1d4a7b"
integrity sha512-BWLQO3nemLDSV5PoE5GPHe1dU9Dth77Kv8/cle9Ujcp4LhPo0KincdPqFH/qKeU/xvW25mgFueflZ1nc4rKuww==
"@typescript/native-preview-linux-x64@7.0.0-dev.20260421.2":
version "7.0.0-dev.20260421.2"
resolved "https://registry.yarnpkg.com/@typescript/native-preview-linux-x64/-/native-preview-linux-x64-7.0.0-dev.20260421.2.tgz#a8ca0d1ceb4659027878b915276ebcfa0ab93130"
integrity sha512-qUrJWTB5/wv4wnRG0TRXElAxc2kykNiRNyEIEqBbLmzDlrcvAW7RRy8MXoY1ZyTiKGMu14itZ3x9oW6+blFpRw==
"@typescript/native-preview-win32-arm64@7.0.0-dev.20260421.2":
version "7.0.0-dev.20260421.2"
resolved "https://registry.yarnpkg.com/@typescript/native-preview-win32-arm64/-/native-preview-win32-arm64-7.0.0-dev.20260421.2.tgz#f1165ba01b22697729c16edd6ae4d1629318a7f4"
integrity sha512-Rc6NsWlZmCs5YUKVzKgwoBOoRUGsPzct4BDMRX0csD1devLBBc4AbUXWKsJRbpwIAnqMO1ld4sNHEb+wXgfNHQ==
"@typescript/native-preview-win32-x64@7.0.0-dev.20260421.2":
version "7.0.0-dev.20260421.2"
resolved "https://registry.yarnpkg.com/@typescript/native-preview-win32-x64/-/native-preview-win32-x64-7.0.0-dev.20260421.2.tgz#01724cea15792e06e9543f1d698141b61fc229fc"
integrity sha512-GQv1+dya1t6EqF2Cpsb+xoozovdX10JUSf6Kl/8xNkTapzmlHd+uMr+8ku3jIASTxoRGn0Mklgjj3MDKrOTuLg==
"@typescript/native-preview@7.0.0-dev.20260421.2":
version "7.0.0-dev.20260421.2"
resolved "https://registry.yarnpkg.com/@typescript/native-preview/-/native-preview-7.0.0-dev.20260421.2.tgz#5c22e3118533f394dc2cade1e290680f978ba7b7"
integrity sha512-CmajHI25HpVWE9R1XFoxr+cphJPxoYD3eFioQtAvXYkMFKnLdICMS9pXre9Pybizb75ejRxjKD5/CVG055rEIg==
optionalDependencies:
"@typescript/native-preview-darwin-arm64" "7.0.0-dev.20260421.2"
"@typescript/native-preview-darwin-x64" "7.0.0-dev.20260421.2"
"@typescript/native-preview-linux-arm" "7.0.0-dev.20260421.2"
"@typescript/native-preview-linux-arm64" "7.0.0-dev.20260421.2"
"@typescript/native-preview-linux-x64" "7.0.0-dev.20260421.2"
"@typescript/native-preview-win32-arm64" "7.0.0-dev.20260421.2"
"@typescript/native-preview-win32-x64" "7.0.0-dev.20260421.2"
"@uiw/codemirror-extensions-basic-setup@4.23.10":
version "4.23.10"
resolved "https://registry.yarnpkg.com/@uiw/codemirror-extensions-basic-setup/-/codemirror-extensions-basic-setup-4.23.10.tgz#e5d901e860a039ac61d955af26a12866e9dc356c"

View File

@@ -4,6 +4,10 @@ const (
TrueConditionLiteral = "true"
SkipConditionLiteral = "__skip__"
ErrorConditionLiteral = "__skip_because_of_error__"
// BodyFullTextSearchDefaultWarning is emitted when a full-text search or "body" searches are hit
// with New JSON Body enhancements.
BodyFullTextSearchDefaultWarning = "Full text searches default to `body.message:string`. Use `body.<key>` to search a different field inside body"
)
var (

View File

@@ -362,6 +362,10 @@ func (v *filterExpressionVisitor) VisitPrimary(ctx *grammar.PrimaryContext) any
v.errors = append(v.errors, fmt.Sprintf("failed to build full text search condition: %s", err.Error()))
return ErrorConditionLiteral
}
if v.bodyJSONEnabled && v.fullTextColumn.Name == "body" {
v.warnings = append(v.warnings, BodyFullTextSearchDefaultWarning)
}
return cond
}
@@ -717,6 +721,10 @@ func (v *filterExpressionVisitor) VisitFullText(ctx *grammar.FullTextContext) an
return ErrorConditionLiteral
}
if v.bodyJSONEnabled && v.fullTextColumn.Name == "body" {
v.warnings = append(v.warnings, BodyFullTextSearchDefaultWarning)
}
return cond
}

View File

@@ -894,12 +894,12 @@ func TestAdjustKey(t *testing.T) {
func TestStmtBuilderBodyField(t *testing.T) {
cases := []struct {
name string
requestType qbtypes.RequestType
query qbtypes.QueryBuilderQuery[qbtypes.LogAggregation]
name string
requestType qbtypes.RequestType
query qbtypes.QueryBuilderQuery[qbtypes.LogAggregation]
enableUseJSONBody bool
expected qbtypes.Statement
expectedErr error
expected qbtypes.Statement
expectedErr error
}{
{
name: "body_exists",
@@ -1039,15 +1039,15 @@ func TestStmtBuilderBodyField(t *testing.T) {
func TestStmtBuilderBodyFullTextSearch(t *testing.T) {
cases := []struct {
name string
requestType qbtypes.RequestType
query qbtypes.QueryBuilderQuery[qbtypes.LogAggregation]
name string
requestType qbtypes.RequestType
query qbtypes.QueryBuilderQuery[qbtypes.LogAggregation]
enableUseJSONBody bool
expected qbtypes.Statement
expectedErr error
expected qbtypes.Statement
expectedErr error
}{
{
name: "body_contains",
name: "fts",
requestType: qbtypes.RequestTypeRaw,
query: qbtypes.QueryBuilderQuery[qbtypes.LogAggregation]{
Signal: telemetrytypes.SignalLogs,
@@ -1056,13 +1056,30 @@ func TestStmtBuilderBodyFullTextSearch(t *testing.T) {
},
enableUseJSONBody: true,
expected: qbtypes.Statement{
Query: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body_v2 as body, attributes_string, attributes_number, attributes_bool, resources_string, scope_string FROM signoz_logs.distributed_logs_v2 WHERE match(LOWER(body_v2.message), LOWER(?)) AND timestamp >= ? AND ts_bucket_start >= ? AND timestamp < ? AND ts_bucket_start <= ? LIMIT ?",
Args: []any{"error", "1747947419000000000", uint64(1747945619), "1747983448000000000", uint64(1747983448), 10},
Query: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body_v2 as body, attributes_string, attributes_number, attributes_bool, resources_string, scope_string FROM signoz_logs.distributed_logs_v2 WHERE match(LOWER(body_v2.message), LOWER(?)) AND timestamp >= ? AND ts_bucket_start >= ? AND timestamp < ? AND ts_bucket_start <= ? LIMIT ?",
Args: []any{"error", "1747947419000000000", uint64(1747945619), "1747983448000000000", uint64(1747983448), 10},
Warnings: []string{querybuilder.BodyFullTextSearchDefaultWarning},
},
expectedErr: nil,
},
{
name: "body_contains_disabled",
name: "fts_2",
requestType: qbtypes.RequestTypeRaw,
query: qbtypes.QueryBuilderQuery[qbtypes.LogAggregation]{
Signal: telemetrytypes.SignalLogs,
Filter: &qbtypes.Filter{Expression: "error"},
Limit: 10,
},
enableUseJSONBody: true,
expected: qbtypes.Statement{
Query: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body_v2 as body, attributes_string, attributes_number, attributes_bool, resources_string, scope_string FROM signoz_logs.distributed_logs_v2 WHERE match(LOWER(body_v2.message), LOWER(?)) AND timestamp >= ? AND ts_bucket_start >= ? AND timestamp < ? AND ts_bucket_start <= ? LIMIT ?",
Args: []any{"error", "1747947419000000000", uint64(1747945619), "1747983448000000000", uint64(1747983448), 10},
Warnings: []string{querybuilder.BodyFullTextSearchDefaultWarning},
},
expectedErr: nil,
},
{
name: "fts_disabled",
requestType: qbtypes.RequestTypeRaw,
query: qbtypes.QueryBuilderQuery[qbtypes.LogAggregation]{
Signal: telemetrytypes.SignalLogs,

View File

@@ -1212,13 +1212,21 @@ def test_message_searches(
"aggregation": "count()",
"validate": lambda r: len(get_rows(r)) == 2 and set(_body_messages(r)) == payment_messages,
},
# FTS — bare keyword
# FTS — String bare keyword
{
"name": "msg.fts_quoted",
"requestType": "raw",
"expression": '"Payment"',
"aggregation": "count()",
"validate": lambda r: len(get_rows(r)) == 2 and all("Payment" in b.get("message", "") for b in _get_bodies(r)),
"validate": lambda r: len(get_rows(r)) == 2 and all("Payment" in b.get("message", "") for b in _get_bodies(r)) and r.json().get("data", {}).get("warning") is not None,
},
# FTS — bare keyword
{
"name": "msg.fts_quoted_without_quotes",
"requestType": "raw",
"expression": "Payment",
"aggregation": "count()",
"validate": lambda r: len(get_rows(r)) == 2 and all("Payment" in b.get("message", "") for b in _get_bodies(r)) and r.json().get("data", {}).get("warning") is not None,
},
# = operator via body.message — tests exact match path
{