mirror of
https://github.com/SigNoz/signoz.git
synced 2026-07-06 14:40:38 +01:00
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: update 47 stale docs links in frontend to current URLs Update documentation links across 19 frontend files to match current signoz.io docs structure after product module restructures. Key changes: - Instrumentation links updated to new OpenTelemetry-prefixed paths - product-features/* links replaced with current locations - Query builder links point to new querying module pages - Alert notification channel links point to setup-alerts-notification - SSO, infra monitoring, and version upgrade links corrected Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: update 278 more stale docs links and broken anchors in frontend - Onboarding md-docs: update instrumentation URLs to canonical paths (django/flask/fastapi/falcon → opentelemetry-python, express/nestjs → javascript/opentelemetry-nodejs, springboot → java/opentelemetry-java, tomcat → java/opentelemetry-tomcat, jboss → java/opentelemetry-jboss, golang → opentelemetry-golang, elixir → opentelemetry-elixir, reactjs → frontend-monitoring/sending-traces-with-opentelemetry) - Onboarding md-docs: update tutorial/* → opentelemetry-collection-agents/*, userguide/hostmetrics → infrastructure-monitoring/hostmetrics, userguide/logs# → userguide/logs_query_builder# - Query builder UI: fix broken anchors after query-builder-v5 page restructure (Having → result-manipulation, Order By → result-manipulation, Limit → result-manipulation, Legend → aggregation-grouping, Group By → aggregation-grouping, Formula → multi-query-analysis, Trace Matching → multi-query-analysis, Reduce → result-manipulation, Aggregation functions → aggregation-grouping, Time aggregation → temporal-aggregation) - Fix Apdex link → alerts-management/apdex-alerts - Fix missing spans link → traces-management/troubleshooting/faqs - Fix cost meter, ClickHouse traces, k8s pod logs anchors - Drop broken anchors where sections were removed from docs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: format CreateAlertRule files after anchor removal Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: revert OnboardingContainer changes (deprecated module) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Vishal Sharma <makeavish786@gmail.com> Co-authored-by: Ubuntu <ubuntu@ip-172-31-24-8.eu-central-1.compute.internal>
242 lines
5.9 KiB
TypeScript
242 lines
5.9 KiB
TypeScript
import { useState } from 'react';
|
|
import { Button, Tooltip } from 'antd';
|
|
import { Typography } from '@signozhq/ui/typography';
|
|
import cx from 'classnames';
|
|
import { cloneDeep, pullAt } from 'lodash-es';
|
|
import { Plus } from '@signozhq/icons';
|
|
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
|
import { QueryFunction } from 'types/api/v5/queryRange';
|
|
import { DataSource, QueryFunctionsTypes } from 'types/common/queryBuilder';
|
|
import { normalizeFunctionName } from 'utils/functionNameNormalizer';
|
|
|
|
import Function from './Function';
|
|
import { toFloat64 } from './utils';
|
|
|
|
import './QueryFunctions.styles.scss';
|
|
|
|
const defaultMetricFunctionStruct: QueryFunction = {
|
|
name: QueryFunctionsTypes.CUTOFF_MIN as any,
|
|
args: [],
|
|
};
|
|
|
|
const defaultLogFunctionStruct: QueryFunction = {
|
|
name: QueryFunctionsTypes.TIME_SHIFT as any,
|
|
args: [],
|
|
};
|
|
|
|
interface QueryFunctionsProps {
|
|
query: IBuilderQuery;
|
|
queryFunctions: QueryFunction[];
|
|
onChange: (functions: QueryFunction[]) => void;
|
|
maxFunctions: number;
|
|
}
|
|
|
|
// SVG component
|
|
function FunctionIcon({
|
|
fillColor = 'white',
|
|
className,
|
|
}: {
|
|
fillColor: string;
|
|
className: string;
|
|
}): JSX.Element {
|
|
return (
|
|
<svg
|
|
width="24"
|
|
height="24"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
className={className}
|
|
>
|
|
<path
|
|
d="M3 18.13C5.71436 18.13 6.8001 16.7728 6.8001 14.3299V8.62978C6.8001 5.91542 8.15728 4.15109 11.1431 4.55824"
|
|
stroke={fillColor}
|
|
strokeWidth="1.995"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
/>
|
|
<path
|
|
d="M3 10.2583H10.7359"
|
|
stroke={fillColor}
|
|
strokeWidth="1.995"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
/>
|
|
<path
|
|
d="M22.0005 11.344L15.2146 18.1299"
|
|
stroke={fillColor}
|
|
strokeWidth="1.995"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
/>
|
|
<path
|
|
d="M15.2146 11.344L22.0005 18.1299"
|
|
stroke={fillColor}
|
|
strokeWidth="1.995"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
/>
|
|
</svg>
|
|
);
|
|
}
|
|
|
|
export default function QueryFunctions({
|
|
query,
|
|
queryFunctions,
|
|
onChange,
|
|
maxFunctions = 3,
|
|
}: QueryFunctionsProps): JSX.Element {
|
|
const [functions, setFunctions] = useState<QueryFunction[]>(
|
|
queryFunctions.map((func) => ({
|
|
...func,
|
|
name: normalizeFunctionName(func.name) as any,
|
|
})),
|
|
);
|
|
|
|
const hasAnomalyFunction = functions.some((func) => func.name === 'anomaly');
|
|
const hasFunctions = functions.length > 0;
|
|
|
|
const handleAddNewFunction = (): void => {
|
|
const defaultFunctionStruct =
|
|
query.dataSource === DataSource.LOGS
|
|
? defaultLogFunctionStruct
|
|
: defaultMetricFunctionStruct;
|
|
|
|
const updatedFunctionsArr = [
|
|
...functions,
|
|
{
|
|
...defaultFunctionStruct,
|
|
},
|
|
];
|
|
|
|
const functionsCopy = cloneDeep(updatedFunctionsArr);
|
|
|
|
const anomalyFuncIndex = functionsCopy.findIndex(
|
|
(func) => func.name === 'anomaly',
|
|
);
|
|
|
|
if (anomalyFuncIndex !== -1) {
|
|
const anomalyFunc = functionsCopy[anomalyFuncIndex];
|
|
|
|
functionsCopy.splice(anomalyFuncIndex, 1);
|
|
functionsCopy.push(anomalyFunc);
|
|
}
|
|
|
|
setFunctions(functionsCopy);
|
|
|
|
onChange(functionsCopy);
|
|
};
|
|
|
|
const handleDeleteFunction = (
|
|
queryFunction: QueryFunction,
|
|
index: number,
|
|
): void => {
|
|
const clonedFunctions = cloneDeep(functions);
|
|
pullAt(clonedFunctions, index);
|
|
|
|
setFunctions(clonedFunctions);
|
|
onChange(clonedFunctions);
|
|
};
|
|
|
|
const handleUpdateFunctionName = (
|
|
func: QueryFunction,
|
|
index: number,
|
|
value: string,
|
|
): void => {
|
|
const updateFunctions = cloneDeep(functions);
|
|
|
|
if (updateFunctions && updateFunctions.length > 0 && updateFunctions[index]) {
|
|
// Normalize function name from backend response to match frontend expectations
|
|
const normalizedValue = normalizeFunctionName(value);
|
|
updateFunctions[index].name = normalizedValue as any;
|
|
setFunctions(updateFunctions);
|
|
onChange(updateFunctions);
|
|
}
|
|
};
|
|
|
|
const handleUpdateFunctionArgs = (
|
|
func: QueryFunction,
|
|
index: number,
|
|
value: string,
|
|
): void => {
|
|
const updateFunctions = cloneDeep(functions);
|
|
|
|
if (updateFunctions && updateFunctions.length > 0 && updateFunctions[index]) {
|
|
updateFunctions[index].args = [
|
|
{
|
|
value:
|
|
updateFunctions[index].name === QueryFunctionsTypes.TIME_SHIFT
|
|
? toFloat64(value)
|
|
: value,
|
|
},
|
|
];
|
|
setFunctions(updateFunctions);
|
|
onChange(updateFunctions);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div
|
|
className={cx(
|
|
'query-functions-container',
|
|
hasFunctions ? 'hasFunctions' : '',
|
|
)}
|
|
>
|
|
<Button
|
|
className="periscope-btn function-btn"
|
|
disabled={hasFunctions}
|
|
onClick={handleAddNewFunction}
|
|
>
|
|
<FunctionIcon className="function-icon" fillColor="var(--l1-foreground)" />
|
|
</Button>
|
|
|
|
<div className="query-functions-list">
|
|
{functions.map((func, index) => (
|
|
<Function
|
|
query={query}
|
|
funcData={func}
|
|
index={index}
|
|
// eslint-disable-next-line react/no-array-index-key
|
|
key={index}
|
|
handleUpdateFunctionArgs={handleUpdateFunctionArgs}
|
|
handleUpdateFunctionName={handleUpdateFunctionName}
|
|
handleDeleteFunction={handleDeleteFunction}
|
|
/>
|
|
))}
|
|
</div>
|
|
|
|
<Tooltip
|
|
title={
|
|
functions && functions.length >= 3 ? (
|
|
`Functions are in early access. You can add a maximum of ${
|
|
hasAnomalyFunction ? 2 : 3
|
|
} function as of now.`
|
|
) : (
|
|
<div style={{ textAlign: 'center' }}>
|
|
Add new function
|
|
<Typography.Link
|
|
style={{ textDecoration: 'underline' }}
|
|
href="https://signoz.io/docs/querying/functions-extended-analysis/?utm_source=product&utm_medium=query-builder"
|
|
target="_blank"
|
|
>
|
|
{' '}
|
|
<br />
|
|
Learn more
|
|
</Typography.Link>
|
|
</div>
|
|
)
|
|
}
|
|
placement="right"
|
|
>
|
|
<Button
|
|
className="periscope-btn add-function-btn"
|
|
disabled={functions && functions.length >= maxFunctions}
|
|
onClick={handleAddNewFunction}
|
|
>
|
|
<Plus size={14} color="var(--l1-foreground)" />
|
|
</Button>
|
|
</Tooltip>
|
|
</div>
|
|
);
|
|
}
|