mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-02 06:20:40 +08:00
Merge branch 'develop' into otel-version-change
This commit is contained in:
commit
1520c1c57d
@ -10,6 +10,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
_ "net/http/pprof" // http profiler
|
_ "net/http/pprof" // http profiler
|
||||||
"os"
|
"os"
|
||||||
|
"regexp"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gorilla/handlers"
|
"github.com/gorilla/handlers"
|
||||||
@ -393,13 +394,14 @@ func (lrw *loggingResponseWriter) Flush() {
|
|||||||
lrw.ResponseWriter.(http.Flusher).Flush()
|
lrw.ResponseWriter.(http.Flusher).Flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractQueryRangeV3Data(path string, r *http.Request) (map[string]interface{}, bool) {
|
func extractQueryRangeData(path string, r *http.Request) (map[string]interface{}, bool) {
|
||||||
pathToExtractBodyFrom := "/api/v3/query_range"
|
pathToExtractBodyFromV3 := "/api/v3/query_range"
|
||||||
|
pathToExtractBodyFromV4 := "/api/v4/query_range"
|
||||||
|
|
||||||
data := map[string]interface{}{}
|
data := map[string]interface{}{}
|
||||||
var postData *v3.QueryRangeParamsV3
|
var postData *v3.QueryRangeParamsV3
|
||||||
|
|
||||||
if path == pathToExtractBodyFrom && (r.Method == "POST") {
|
if (r.Method == "POST") && ((path == pathToExtractBodyFromV3) || (path == pathToExtractBodyFromV4)) {
|
||||||
if r.Body != nil {
|
if r.Body != nil {
|
||||||
bodyBytes, err := io.ReadAll(r.Body)
|
bodyBytes, err := io.ReadAll(r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -417,6 +419,25 @@ func extractQueryRangeV3Data(path string, r *http.Request) (map[string]interface
|
|||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
referrer := r.Header.Get("Referer")
|
||||||
|
|
||||||
|
dashboardMatched, err := regexp.MatchString(`/dashboard/[a-zA-Z0-9\-]+/(new|edit)(?:\?.*)?$`, referrer)
|
||||||
|
if err != nil {
|
||||||
|
zap.L().Error("error while matching the referrer", zap.Error(err))
|
||||||
|
}
|
||||||
|
alertMatched, err := regexp.MatchString(`/alerts/(new|edit)(?:\?.*)?$`, referrer)
|
||||||
|
if err != nil {
|
||||||
|
zap.L().Error("error while matching the alert: ", zap.Error(err))
|
||||||
|
}
|
||||||
|
logsExplorerMatched, err := regexp.MatchString(`/logs/logs-explorer(?:\?.*)?$`, referrer)
|
||||||
|
if err != nil {
|
||||||
|
zap.L().Error("error while matching the logs explorer: ", zap.Error(err))
|
||||||
|
}
|
||||||
|
traceExplorerMatched, err := regexp.MatchString(`/traces-explorer(?:\?.*)?$`, referrer)
|
||||||
|
if err != nil {
|
||||||
|
zap.L().Error("error while matching the trace explorer: ", zap.Error(err))
|
||||||
|
}
|
||||||
|
|
||||||
signozMetricsUsed := false
|
signozMetricsUsed := false
|
||||||
signozLogsUsed := false
|
signozLogsUsed := false
|
||||||
signozTracesUsed := false
|
signozTracesUsed := false
|
||||||
@ -445,6 +466,20 @@ func extractQueryRangeV3Data(path string, r *http.Request) (map[string]interface
|
|||||||
data["tracesUsed"] = signozTracesUsed
|
data["tracesUsed"] = signozTracesUsed
|
||||||
userEmail, err := baseauth.GetEmailFromJwt(r.Context())
|
userEmail, err := baseauth.GetEmailFromJwt(r.Context())
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
// switch case to set data["screen"] based on the referrer
|
||||||
|
switch {
|
||||||
|
case dashboardMatched:
|
||||||
|
data["screen"] = "panel"
|
||||||
|
case alertMatched:
|
||||||
|
data["screen"] = "alert"
|
||||||
|
case logsExplorerMatched:
|
||||||
|
data["screen"] = "logs-explorer"
|
||||||
|
case traceExplorerMatched:
|
||||||
|
data["screen"] = "traces-explorer"
|
||||||
|
default:
|
||||||
|
data["screen"] = "unknown"
|
||||||
|
return data, true
|
||||||
|
}
|
||||||
telemetry.GetInstance().SendEvent(telemetry.TELEMETRY_EVENT_QUERY_RANGE_API, data, userEmail, true, false)
|
telemetry.GetInstance().SendEvent(telemetry.TELEMETRY_EVENT_QUERY_RANGE_API, data, userEmail, true, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -472,7 +507,7 @@ func (s *Server) analyticsMiddleware(next http.Handler) http.Handler {
|
|||||||
route := mux.CurrentRoute(r)
|
route := mux.CurrentRoute(r)
|
||||||
path, _ := route.GetPathTemplate()
|
path, _ := route.GetPathTemplate()
|
||||||
|
|
||||||
queryRangeV3data, metadataExists := extractQueryRangeV3Data(path, r)
|
queryRangeData, metadataExists := extractQueryRangeData(path, r)
|
||||||
getActiveLogs(path, r)
|
getActiveLogs(path, r)
|
||||||
|
|
||||||
lrw := NewLoggingResponseWriter(w)
|
lrw := NewLoggingResponseWriter(w)
|
||||||
@ -480,7 +515,7 @@ func (s *Server) analyticsMiddleware(next http.Handler) http.Handler {
|
|||||||
|
|
||||||
data := map[string]interface{}{"path": path, "statusCode": lrw.statusCode}
|
data := map[string]interface{}{"path": path, "statusCode": lrw.statusCode}
|
||||||
if metadataExists {
|
if metadataExists {
|
||||||
for key, value := range queryRangeV3data {
|
for key, value := range queryRangeData {
|
||||||
data[key] = value
|
data[key] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import { QueryFunctionsTypes } from 'types/common/queryBuilder';
|
import { QueryFunctionsTypes } from 'types/common/queryBuilder';
|
||||||
import { SelectOption } from 'types/common/select';
|
import { SelectOption } from 'types/common/select';
|
||||||
|
|
||||||
export const queryFunctionOptions: SelectOption<string, string>[] = [
|
export const metricQueryFunctionOptions: SelectOption<string, string>[] = [
|
||||||
{
|
{
|
||||||
value: QueryFunctionsTypes.CUTOFF_MIN,
|
value: QueryFunctionsTypes.CUTOFF_MIN,
|
||||||
label: 'Cut Off Min',
|
label: 'Cut Off Min',
|
||||||
@ -65,6 +65,12 @@ export const queryFunctionOptions: SelectOption<string, string>[] = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const logsQueryFunctionOptions: SelectOption<string, string>[] = [
|
||||||
|
{
|
||||||
|
value: QueryFunctionsTypes.TIME_SHIFT,
|
||||||
|
label: 'Time Shift',
|
||||||
|
},
|
||||||
|
];
|
||||||
interface QueryFunctionConfigType {
|
interface QueryFunctionConfigType {
|
||||||
[key: string]: {
|
[key: string]: {
|
||||||
showInput: boolean;
|
showInput: boolean;
|
||||||
|
@ -56,8 +56,9 @@ function QuerySection({
|
|||||||
initialDataSource: ALERTS_DATA_SOURCE_MAP[alertType],
|
initialDataSource: ALERTS_DATA_SOURCE_MAP[alertType],
|
||||||
}}
|
}}
|
||||||
showFunctions={
|
showFunctions={
|
||||||
alertType === AlertTypes.METRICS_BASED_ALERT &&
|
(alertType === AlertTypes.METRICS_BASED_ALERT &&
|
||||||
alertDef.version === ENTITY_VERSION_V4
|
alertDef.version === ENTITY_VERSION_V4) ||
|
||||||
|
alertType === AlertTypes.LOGS_BASED_ALERT
|
||||||
}
|
}
|
||||||
version={alertDef.version || 'v3'}
|
version={alertDef.version || 'v3'}
|
||||||
/>
|
/>
|
||||||
|
@ -77,6 +77,7 @@
|
|||||||
.qb-entity-options {
|
.qb-entity-options {
|
||||||
.options {
|
.options {
|
||||||
border-color: var(--bg-vanilla-300);
|
border-color: var(--bg-vanilla-300);
|
||||||
|
box-shadow: none;
|
||||||
|
|
||||||
.periscope-btn {
|
.periscope-btn {
|
||||||
border-color: var(--bg-vanilla-300);
|
border-color: var(--bg-vanilla-300);
|
||||||
|
@ -17,6 +17,7 @@ import {
|
|||||||
IBuilderQuery,
|
IBuilderQuery,
|
||||||
QueryFunctionProps,
|
QueryFunctionProps,
|
||||||
} from 'types/api/queryBuilder/queryBuilderData';
|
} from 'types/api/queryBuilder/queryBuilderData';
|
||||||
|
import { DataSource } from 'types/common/queryBuilder';
|
||||||
|
|
||||||
import QueryFunctions from '../QueryFunctions/QueryFunctions';
|
import QueryFunctions from '../QueryFunctions/QueryFunctions';
|
||||||
|
|
||||||
@ -57,6 +58,8 @@ export default function QBEntityOptions({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isLogsDataSource = query?.dataSource === DataSource.LOGS;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<div className="qb-entity-options">
|
<div className="qb-entity-options">
|
||||||
@ -97,12 +100,14 @@ export default function QBEntityOptions({
|
|||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
{showFunctions &&
|
{showFunctions &&
|
||||||
isMetricsDataSource &&
|
(isMetricsDataSource || isLogsDataSource) &&
|
||||||
query &&
|
query &&
|
||||||
onQueryFunctionsUpdates && (
|
onQueryFunctionsUpdates && (
|
||||||
<QueryFunctions
|
<QueryFunctions
|
||||||
|
query={query}
|
||||||
queryFunctions={query.functions}
|
queryFunctions={query.functions}
|
||||||
onChange={onQueryFunctionsUpdates}
|
onChange={onQueryFunctionsUpdates}
|
||||||
|
maxFunctions={isLogsDataSource ? 1 : 3}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Button.Group>
|
</Button.Group>
|
||||||
|
@ -36,6 +36,7 @@ import {
|
|||||||
} from 'react';
|
} from 'react';
|
||||||
import { useLocation } from 'react-use';
|
import { useLocation } from 'react-use';
|
||||||
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
|
import { DataSource } from 'types/common/queryBuilder';
|
||||||
import { transformToUpperCase } from 'utils/transformToUpperCase';
|
import { transformToUpperCase } from 'utils/transformToUpperCase';
|
||||||
|
|
||||||
import QBEntityOptions from '../QBEntityOptions/QBEntityOptions';
|
import QBEntityOptions from '../QBEntityOptions/QBEntityOptions';
|
||||||
@ -324,7 +325,10 @@ export const Query = memo(function Query({
|
|||||||
<QBEntityOptions
|
<QBEntityOptions
|
||||||
isMetricsDataSource={isMetricsDataSource}
|
isMetricsDataSource={isMetricsDataSource}
|
||||||
showFunctions={
|
showFunctions={
|
||||||
(version && version === ENTITY_VERSION_V4) || showFunctions || false
|
(version && version === ENTITY_VERSION_V4) ||
|
||||||
|
query.dataSource === DataSource.LOGS ||
|
||||||
|
showFunctions ||
|
||||||
|
false
|
||||||
}
|
}
|
||||||
isCollapsed={isCollapse}
|
isCollapsed={isCollapse}
|
||||||
entityType="query"
|
entityType="query"
|
||||||
|
@ -2,15 +2,21 @@
|
|||||||
import { Button, Flex, Input, Select } from 'antd';
|
import { Button, Flex, Input, Select } from 'antd';
|
||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
import {
|
import {
|
||||||
queryFunctionOptions,
|
logsQueryFunctionOptions,
|
||||||
|
metricQueryFunctionOptions,
|
||||||
queryFunctionsTypesConfig,
|
queryFunctionsTypesConfig,
|
||||||
} from 'constants/queryFunctionOptions';
|
} from 'constants/queryFunctionOptions';
|
||||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||||
import { debounce, isNil } from 'lodash-es';
|
import { debounce, isNil } from 'lodash-es';
|
||||||
import { X } from 'lucide-react';
|
import { X } from 'lucide-react';
|
||||||
import { QueryFunctionProps } from 'types/api/queryBuilder/queryBuilderData';
|
import {
|
||||||
|
IBuilderQuery,
|
||||||
|
QueryFunctionProps,
|
||||||
|
} from 'types/api/queryBuilder/queryBuilderData';
|
||||||
|
import { DataSource } from 'types/common/queryBuilder';
|
||||||
|
|
||||||
interface FunctionProps {
|
interface FunctionProps {
|
||||||
|
query: IBuilderQuery;
|
||||||
funcData: QueryFunctionProps;
|
funcData: QueryFunctionProps;
|
||||||
index: any;
|
index: any;
|
||||||
handleUpdateFunctionArgs: any;
|
handleUpdateFunctionArgs: any;
|
||||||
@ -19,6 +25,7 @@ interface FunctionProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function Function({
|
export default function Function({
|
||||||
|
query,
|
||||||
funcData,
|
funcData,
|
||||||
index,
|
index,
|
||||||
handleUpdateFunctionArgs,
|
handleUpdateFunctionArgs,
|
||||||
@ -44,6 +51,12 @@ export default function Function({
|
|||||||
500,
|
500,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// update the logic when we start supporting functions for traces
|
||||||
|
const functionOptions =
|
||||||
|
query.dataSource === DataSource.LOGS
|
||||||
|
? logsQueryFunctionOptions
|
||||||
|
: metricQueryFunctionOptions;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex className="query-function">
|
<Flex className="query-function">
|
||||||
<Select
|
<Select
|
||||||
@ -62,7 +75,7 @@ export default function Function({
|
|||||||
boxShadow: `4px 10px 16px 2px rgba(0, 0, 0, 0.20)`,
|
boxShadow: `4px 10px 16px 2px rgba(0, 0, 0, 0.20)`,
|
||||||
}}
|
}}
|
||||||
placement="bottomRight"
|
placement="bottomRight"
|
||||||
options={queryFunctionOptions}
|
options={functionOptions}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{showInput && (
|
{showInput && (
|
||||||
|
@ -6,19 +6,29 @@ import { useIsDarkMode } from 'hooks/useDarkMode';
|
|||||||
import { cloneDeep, pullAt } from 'lodash-es';
|
import { cloneDeep, pullAt } from 'lodash-es';
|
||||||
import { Plus } from 'lucide-react';
|
import { Plus } from 'lucide-react';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { QueryFunctionProps } from 'types/api/queryBuilder/queryBuilderData';
|
import {
|
||||||
import { QueryFunctionsTypes } from 'types/common/queryBuilder';
|
IBuilderQuery,
|
||||||
|
QueryFunctionProps,
|
||||||
|
} from 'types/api/queryBuilder/queryBuilderData';
|
||||||
|
import { DataSource, QueryFunctionsTypes } from 'types/common/queryBuilder';
|
||||||
|
|
||||||
import Function from './Function';
|
import Function from './Function';
|
||||||
|
|
||||||
const defaultFunctionStruct: QueryFunctionProps = {
|
const defaultMetricFunctionStruct: QueryFunctionProps = {
|
||||||
name: QueryFunctionsTypes.CUTOFF_MIN,
|
name: QueryFunctionsTypes.CUTOFF_MIN,
|
||||||
args: [],
|
args: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const defaultLogFunctionStruct: QueryFunctionProps = {
|
||||||
|
name: QueryFunctionsTypes.TIME_SHIFT,
|
||||||
|
args: [],
|
||||||
|
};
|
||||||
|
|
||||||
interface QueryFunctionsProps {
|
interface QueryFunctionsProps {
|
||||||
|
query: IBuilderQuery;
|
||||||
queryFunctions: QueryFunctionProps[];
|
queryFunctions: QueryFunctionProps[];
|
||||||
onChange: (functions: QueryFunctionProps[]) => void;
|
onChange: (functions: QueryFunctionProps[]) => void;
|
||||||
|
maxFunctions: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SVG component
|
// SVG component
|
||||||
@ -71,8 +81,10 @@ function FunctionIcon({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function QueryFunctions({
|
export default function QueryFunctions({
|
||||||
|
query,
|
||||||
queryFunctions,
|
queryFunctions,
|
||||||
onChange,
|
onChange,
|
||||||
|
maxFunctions = 3,
|
||||||
}: QueryFunctionsProps): JSX.Element {
|
}: QueryFunctionsProps): JSX.Element {
|
||||||
const [functions, setFunctions] = useState<QueryFunctionProps[]>(
|
const [functions, setFunctions] = useState<QueryFunctionProps[]>(
|
||||||
queryFunctions,
|
queryFunctions,
|
||||||
@ -81,6 +93,11 @@ export default function QueryFunctions({
|
|||||||
const isDarkMode = useIsDarkMode();
|
const isDarkMode = useIsDarkMode();
|
||||||
|
|
||||||
const handleAddNewFunction = (): void => {
|
const handleAddNewFunction = (): void => {
|
||||||
|
const defaultFunctionStruct =
|
||||||
|
query.dataSource === DataSource.LOGS
|
||||||
|
? defaultLogFunctionStruct
|
||||||
|
: defaultMetricFunctionStruct;
|
||||||
|
|
||||||
const updatedFunctionsArr = [
|
const updatedFunctionsArr = [
|
||||||
...functions,
|
...functions,
|
||||||
{
|
{
|
||||||
@ -149,6 +166,7 @@ export default function QueryFunctions({
|
|||||||
<div className="query-functions-list">
|
<div className="query-functions-list">
|
||||||
{functions.map((func, index) => (
|
{functions.map((func, index) => (
|
||||||
<Function
|
<Function
|
||||||
|
query={query}
|
||||||
funcData={func}
|
funcData={func}
|
||||||
index={index}
|
index={index}
|
||||||
// eslint-disable-next-line react/no-array-index-key
|
// eslint-disable-next-line react/no-array-index-key
|
||||||
@ -170,7 +188,7 @@ export default function QueryFunctions({
|
|||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
className="periscope-btn add-function-btn"
|
className="periscope-btn add-function-btn"
|
||||||
disabled={functions && functions.length >= 3}
|
disabled={functions && functions.length >= maxFunctions}
|
||||||
onClick={handleAddNewFunction}
|
onClick={handleAddNewFunction}
|
||||||
>
|
>
|
||||||
<Plus size={14} color={!isDarkMode ? '#0B0C0E' : 'white'} />
|
<Plus size={14} color={!isDarkMode ? '#0B0C0E' : 'white'} />
|
||||||
|
@ -294,7 +294,10 @@ export const useQueryOperations: UseQueryOperations = ({
|
|||||||
...query,
|
...query,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (newQuery.dataSource === DataSource.METRICS) {
|
if (
|
||||||
|
newQuery.dataSource === DataSource.METRICS ||
|
||||||
|
newQuery.dataSource === DataSource.LOGS
|
||||||
|
) {
|
||||||
newQuery.functions = functions;
|
newQuery.functions = functions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,6 +307,7 @@ export const useQueryOperations: UseQueryOperations = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const isMetricsDataSource = query.dataSource === DataSource.METRICS;
|
const isMetricsDataSource = query.dataSource === DataSource.METRICS;
|
||||||
|
const isLogsDataSource = query.dataSource === DataSource.LOGS;
|
||||||
|
|
||||||
const isTracePanelType = panelType === PANEL_TYPES.TRACE;
|
const isTracePanelType = panelType === PANEL_TYPES.TRACE;
|
||||||
|
|
||||||
@ -346,6 +350,7 @@ export const useQueryOperations: UseQueryOperations = ({
|
|||||||
return {
|
return {
|
||||||
isTracePanelType,
|
isTracePanelType,
|
||||||
isMetricsDataSource,
|
isMetricsDataSource,
|
||||||
|
isLogsDataSource,
|
||||||
operators,
|
operators,
|
||||||
spaceAggregationOptions,
|
spaceAggregationOptions,
|
||||||
listOfAdditionalFilters,
|
listOfAdditionalFilters,
|
||||||
|
@ -15,7 +15,7 @@ function Integrations(): JSX.Element {
|
|||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
||||||
const { trackPageView, trackEvent } = useAnalytics();
|
const { trackEvent } = useAnalytics();
|
||||||
|
|
||||||
const selectedIntegration = useMemo(() => urlQuery.get('integration'), [
|
const selectedIntegration = useMemo(() => urlQuery.get('integration'), [
|
||||||
urlQuery,
|
urlQuery,
|
||||||
@ -42,7 +42,7 @@ function Integrations(): JSX.Element {
|
|||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
trackPageView(location.pathname);
|
trackEvent(INTEGRATION_TELEMETRY_EVENTS.INTEGRATIONS_LIST_VISITED);
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ export const handleContactSupport = (isCloudUser: boolean): void => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const INTEGRATION_TELEMETRY_EVENTS = {
|
export const INTEGRATION_TELEMETRY_EVENTS = {
|
||||||
|
INTEGRATIONS_LIST_VISITED: 'Integrations Page: Visited the list page',
|
||||||
INTEGRATIONS_ITEM_LIST_CLICKED: 'Integrations Page: Clicked an integration',
|
INTEGRATIONS_ITEM_LIST_CLICKED: 'Integrations Page: Clicked an integration',
|
||||||
INTEGRATIONS_DETAIL_CONNECT:
|
INTEGRATIONS_DETAIL_CONNECT:
|
||||||
'Integrations Detail Page: Clicked connect integration button',
|
'Integrations Detail Page: Clicked connect integration button',
|
||||||
|
@ -50,6 +50,7 @@ import (
|
|||||||
"go.signoz.io/signoz/pkg/query-service/auth"
|
"go.signoz.io/signoz/pkg/query-service/auth"
|
||||||
"go.signoz.io/signoz/pkg/query-service/common"
|
"go.signoz.io/signoz/pkg/query-service/common"
|
||||||
"go.signoz.io/signoz/pkg/query-service/constants"
|
"go.signoz.io/signoz/pkg/query-service/constants"
|
||||||
|
"go.signoz.io/signoz/pkg/query-service/dao"
|
||||||
am "go.signoz.io/signoz/pkg/query-service/integrations/alertManager"
|
am "go.signoz.io/signoz/pkg/query-service/integrations/alertManager"
|
||||||
"go.signoz.io/signoz/pkg/query-service/interfaces"
|
"go.signoz.io/signoz/pkg/query-service/interfaces"
|
||||||
"go.signoz.io/signoz/pkg/query-service/model"
|
"go.signoz.io/signoz/pkg/query-service/model"
|
||||||
@ -879,7 +880,7 @@ func (r *ClickHouseReader) GetServices(ctx context.Context, queryParams *model.G
|
|||||||
zap.L().Error("Error building query with tag params", zap.Error(errStatus))
|
zap.L().Error("Error building query with tag params", zap.Error(errStatus))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
query += subQuery
|
errorQuery += subQuery
|
||||||
args = append(args, argsSubQuery...)
|
args = append(args, argsSubQuery...)
|
||||||
err = r.db.QueryRow(ctx, errorQuery, args...).Scan(&numErrors)
|
err = r.db.QueryRow(ctx, errorQuery, args...).Scan(&numErrors)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -3618,6 +3619,15 @@ func (r *ClickHouseReader) GetSavedViewsInfo(ctx context.Context) (*model.SavedV
|
|||||||
return &savedViewsInfo, nil
|
return &savedViewsInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *ClickHouseReader) GetUsers(ctx context.Context) ([]model.UserPayload, error) {
|
||||||
|
|
||||||
|
users, apiErr := dao.DB().GetUsers(ctx)
|
||||||
|
if apiErr != nil {
|
||||||
|
return nil, apiErr.Err
|
||||||
|
}
|
||||||
|
return users, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *ClickHouseReader) GetLogFields(ctx context.Context) (*model.GetFieldsResponse, *model.ApiError) {
|
func (r *ClickHouseReader) GetLogFields(ctx context.Context) (*model.GetFieldsResponse, *model.ApiError) {
|
||||||
// response will contain top level fields from the otel log model
|
// response will contain top level fields from the otel log model
|
||||||
response := model.GetFieldsResponse{
|
response := model.GetFieldsResponse{
|
||||||
|
@ -3722,6 +3722,7 @@ func (aH *APIHandler) queryRangeV4(ctx context.Context, queryRangeParams *v3.Que
|
|||||||
}
|
}
|
||||||
|
|
||||||
if queryRangeParams.CompositeQuery.QueryType == v3.QueryTypeBuilder {
|
if queryRangeParams.CompositeQuery.QueryType == v3.QueryTypeBuilder {
|
||||||
|
|
||||||
result, err = postProcessResult(result, queryRangeParams)
|
result, err = postProcessResult(result, queryRangeParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3786,6 +3787,12 @@ func postProcessResult(result []*v3.Result, queryRangeParams *v3.QueryRangeParam
|
|||||||
// We apply the functions here it's easier to add new functions
|
// We apply the functions here it's easier to add new functions
|
||||||
applyFunctions(result, queryRangeParams)
|
applyFunctions(result, queryRangeParams)
|
||||||
|
|
||||||
|
// expressions are executed at query serivce so the value of time.now in the invdividual
|
||||||
|
// queries will be different so for table panel we are making it same.
|
||||||
|
if queryRangeParams.CompositeQuery.PanelType == v3.PanelTypeTable {
|
||||||
|
tablePanelResultProcessor(result)
|
||||||
|
}
|
||||||
|
|
||||||
for _, query := range queryRangeParams.CompositeQuery.BuilderQueries {
|
for _, query := range queryRangeParams.CompositeQuery.BuilderQueries {
|
||||||
// The way we distinguish between a formula and a query is by checking if the expression
|
// The way we distinguish between a formula and a query is by checking if the expression
|
||||||
// is the same as the query name
|
// is the same as the query name
|
||||||
@ -3838,3 +3845,18 @@ func applyFunctions(results []*v3.Result, queryRangeParams *v3.QueryRangeParamsV
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func tablePanelResultProcessor(results []*v3.Result) {
|
||||||
|
var ts int64
|
||||||
|
for ridx := range results {
|
||||||
|
for sidx := range results[ridx].Series {
|
||||||
|
for pidx := range results[ridx].Series[sidx].Points {
|
||||||
|
if ts == 0 {
|
||||||
|
ts = results[ridx].Series[sidx].Points[pidx].Timestamp
|
||||||
|
} else {
|
||||||
|
results[ridx].Series[sidx].Points[pidx].Timestamp = ts
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -18,6 +18,61 @@ import (
|
|||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func prepareLogsQuery(ctx context.Context,
|
||||||
|
start,
|
||||||
|
end int64,
|
||||||
|
builderQuery *v3.BuilderQuery,
|
||||||
|
params *v3.QueryRangeParamsV3,
|
||||||
|
preferRPM bool,
|
||||||
|
) (string, error) {
|
||||||
|
query := ""
|
||||||
|
|
||||||
|
if params == nil || builderQuery == nil {
|
||||||
|
return query, fmt.Errorf("params and builderQuery cannot be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
// for ts query with limit replace it as it is already formed
|
||||||
|
if params.CompositeQuery.PanelType == v3.PanelTypeGraph && builderQuery.Limit > 0 && len(builderQuery.GroupBy) > 0 {
|
||||||
|
limitQuery, err := logsV3.PrepareLogsQuery(
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
params.CompositeQuery.QueryType,
|
||||||
|
params.CompositeQuery.PanelType,
|
||||||
|
builderQuery,
|
||||||
|
logsV3.Options{GraphLimitQtype: constants.FirstQueryGraphLimit, PreferRPM: preferRPM},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return query, err
|
||||||
|
}
|
||||||
|
placeholderQuery, err := logsV3.PrepareLogsQuery(
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
params.CompositeQuery.QueryType,
|
||||||
|
params.CompositeQuery.PanelType,
|
||||||
|
builderQuery,
|
||||||
|
logsV3.Options{GraphLimitQtype: constants.SecondQueryGraphLimit, PreferRPM: preferRPM},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return query, err
|
||||||
|
}
|
||||||
|
query = strings.Replace(placeholderQuery, "#LIMIT_PLACEHOLDER", limitQuery, 1)
|
||||||
|
return query, err
|
||||||
|
}
|
||||||
|
|
||||||
|
query, err := logsV3.PrepareLogsQuery(
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
params.CompositeQuery.QueryType,
|
||||||
|
params.CompositeQuery.PanelType,
|
||||||
|
builderQuery,
|
||||||
|
logsV3.Options{PreferRPM: preferRPM},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return query, err
|
||||||
|
}
|
||||||
|
return query, err
|
||||||
|
}
|
||||||
|
|
||||||
func (q *querier) runBuilderQuery(
|
func (q *querier) runBuilderQuery(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
builderQuery *v3.BuilderQuery,
|
builderQuery *v3.BuilderQuery,
|
||||||
@ -48,48 +103,8 @@ func (q *querier) runBuilderQuery(
|
|||||||
if builderQuery.DataSource == v3.DataSourceLogs {
|
if builderQuery.DataSource == v3.DataSourceLogs {
|
||||||
var query string
|
var query string
|
||||||
var err error
|
var err error
|
||||||
// for ts query with limit replace it as it is already formed
|
if _, ok := cacheKeys[queryName]; !ok {
|
||||||
if params.CompositeQuery.PanelType == v3.PanelTypeGraph && builderQuery.Limit > 0 && len(builderQuery.GroupBy) > 0 {
|
query, err = prepareLogsQuery(ctx, start, end, builderQuery, params, preferRPM)
|
||||||
limitQuery, err := logsV3.PrepareLogsQuery(
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
params.CompositeQuery.QueryType,
|
|
||||||
params.CompositeQuery.PanelType,
|
|
||||||
builderQuery,
|
|
||||||
logsV3.Options{GraphLimitQtype: constants.FirstQueryGraphLimit, PreferRPM: preferRPM},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
ch <- channelResult{Err: err, Name: queryName, Query: limitQuery, Series: nil}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
placeholderQuery, err := logsV3.PrepareLogsQuery(
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
params.CompositeQuery.QueryType,
|
|
||||||
params.CompositeQuery.PanelType,
|
|
||||||
builderQuery,
|
|
||||||
logsV3.Options{GraphLimitQtype: constants.SecondQueryGraphLimit, PreferRPM: preferRPM},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
ch <- channelResult{Err: err, Name: queryName, Query: placeholderQuery, Series: nil}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
query = strings.Replace(placeholderQuery, "#LIMIT_PLACEHOLDER", limitQuery, 1)
|
|
||||||
} else {
|
|
||||||
query, err = logsV3.PrepareLogsQuery(
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
params.CompositeQuery.QueryType,
|
|
||||||
params.CompositeQuery.PanelType,
|
|
||||||
builderQuery,
|
|
||||||
logsV3.Options{PreferRPM: preferRPM},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
ch <- channelResult{Err: err, Name: queryName, Query: query, Series: nil}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ch <- channelResult{Err: err, Name: queryName, Query: query, Series: nil}
|
ch <- channelResult{Err: err, Name: queryName, Query: query, Series: nil}
|
||||||
return
|
return
|
||||||
@ -98,6 +113,74 @@ func (q *querier) runBuilderQuery(
|
|||||||
ch <- channelResult{Err: err, Name: queryName, Query: query, Series: series}
|
ch <- channelResult{Err: err, Name: queryName, Query: query, Series: series}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
cacheKey := cacheKeys[queryName]
|
||||||
|
var cachedData []byte
|
||||||
|
if !params.NoCache && q.cache != nil {
|
||||||
|
var retrieveStatus status.RetrieveStatus
|
||||||
|
data, retrieveStatus, err := q.cache.Retrieve(cacheKey, true)
|
||||||
|
zap.L().Info("cache retrieve status", zap.String("status", retrieveStatus.String()))
|
||||||
|
if err == nil {
|
||||||
|
cachedData = data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
misses := q.findMissingTimeRanges(start, end, params.Step, cachedData)
|
||||||
|
missedSeries := make([]*v3.Series, 0)
|
||||||
|
cachedSeries := make([]*v3.Series, 0)
|
||||||
|
for _, miss := range misses {
|
||||||
|
query, err = prepareLogsQuery(ctx, miss.start, miss.end, builderQuery, params, preferRPM)
|
||||||
|
if err != nil {
|
||||||
|
ch <- channelResult{Err: err, Name: queryName, Query: query, Series: nil}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
series, err := q.execClickHouseQuery(ctx, query)
|
||||||
|
if err != nil {
|
||||||
|
ch <- channelResult{
|
||||||
|
Err: err,
|
||||||
|
Name: queryName,
|
||||||
|
Query: query,
|
||||||
|
Series: nil,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
missedSeries = append(missedSeries, series...)
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(cachedData, &cachedSeries); err != nil && cachedData != nil {
|
||||||
|
zap.L().Error("error unmarshalling cached data", zap.Error(err))
|
||||||
|
}
|
||||||
|
mergedSeries := mergeSerieses(cachedSeries, missedSeries)
|
||||||
|
|
||||||
|
var mergedSeriesData []byte
|
||||||
|
var marshallingErr error
|
||||||
|
missedSeriesLen := len(missedSeries)
|
||||||
|
if missedSeriesLen > 0 && !params.NoCache && q.cache != nil {
|
||||||
|
// caching the data
|
||||||
|
mergedSeriesData, marshallingErr = json.Marshal(mergedSeries)
|
||||||
|
if marshallingErr != nil {
|
||||||
|
zap.L().Error("error marshalling merged series", zap.Error(marshallingErr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// response doesn't need everything
|
||||||
|
filterCachedPoints(mergedSeries, start, end)
|
||||||
|
|
||||||
|
ch <- channelResult{
|
||||||
|
Err: nil,
|
||||||
|
Name: queryName,
|
||||||
|
Series: mergedSeries,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache the seriesList for future queries
|
||||||
|
if missedSeriesLen > 0 && !params.NoCache && q.cache != nil && marshallingErr == nil {
|
||||||
|
// caching the data
|
||||||
|
err = q.cache.Store(cacheKey, mergedSeriesData, time.Hour)
|
||||||
|
if err != nil {
|
||||||
|
zap.L().Error("error storing merged series", zap.Error(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if builderQuery.DataSource == v3.DataSourceTraces {
|
if builderQuery.DataSource == v3.DataSourceTraces {
|
||||||
|
|
||||||
@ -211,6 +294,19 @@ func (q *querier) runBuilderQuery(
|
|||||||
zap.L().Error("error unmarshalling cached data", zap.Error(err))
|
zap.L().Error("error unmarshalling cached data", zap.Error(err))
|
||||||
}
|
}
|
||||||
mergedSeries := mergeSerieses(cachedSeries, missedSeries)
|
mergedSeries := mergeSerieses(cachedSeries, missedSeries)
|
||||||
|
var mergedSeriesData []byte
|
||||||
|
var marshallingErr error
|
||||||
|
missedSeriesLen := len(missedSeries)
|
||||||
|
if missedSeriesLen > 0 && !params.NoCache && q.cache != nil {
|
||||||
|
// caching the data
|
||||||
|
mergedSeriesData, marshallingErr = json.Marshal(mergedSeries)
|
||||||
|
if marshallingErr != nil {
|
||||||
|
zap.S().Error("error marshalling merged series", zap.Error(marshallingErr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// response doesn't need everything
|
||||||
|
filterCachedPoints(mergedSeries, params.Start, params.End)
|
||||||
|
|
||||||
ch <- channelResult{
|
ch <- channelResult{
|
||||||
Err: nil,
|
Err: nil,
|
||||||
@ -218,13 +314,8 @@ func (q *querier) runBuilderQuery(
|
|||||||
Series: mergedSeries,
|
Series: mergedSeries,
|
||||||
}
|
}
|
||||||
// Cache the seriesList for future queries
|
// Cache the seriesList for future queries
|
||||||
if len(missedSeries) > 0 && !params.NoCache && q.cache != nil {
|
if missedSeriesLen > 0 && !params.NoCache && q.cache != nil && marshallingErr == nil {
|
||||||
mergedSeriesData, err := json.Marshal(mergedSeries)
|
err := q.cache.Store(cacheKey, mergedSeriesData, time.Hour)
|
||||||
if err != nil {
|
|
||||||
zap.L().Error("error marshalling merged series", zap.Error(err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = q.cache.Store(cacheKey, mergedSeriesData, time.Hour)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zap.L().Error("error storing merged series", zap.Error(err))
|
zap.L().Error("error storing merged series", zap.Error(err))
|
||||||
return
|
return
|
||||||
@ -293,18 +384,27 @@ func (q *querier) runBuilderExpression(
|
|||||||
}
|
}
|
||||||
mergedSeries := mergeSerieses(cachedSeries, missedSeries)
|
mergedSeries := mergeSerieses(cachedSeries, missedSeries)
|
||||||
|
|
||||||
|
var mergedSeriesData []byte
|
||||||
|
missedSeriesLen := len(missedSeries)
|
||||||
|
var marshallingErr error
|
||||||
|
if missedSeriesLen > 0 && !params.NoCache && q.cache != nil {
|
||||||
|
// caching the data
|
||||||
|
mergedSeriesData, marshallingErr = json.Marshal(mergedSeries)
|
||||||
|
if marshallingErr != nil {
|
||||||
|
zap.S().Error("error marshalling merged series", zap.Error(marshallingErr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// response doesn't need everything
|
||||||
|
filterCachedPoints(mergedSeries, params.Start, params.End)
|
||||||
|
|
||||||
ch <- channelResult{
|
ch <- channelResult{
|
||||||
Err: nil,
|
Err: nil,
|
||||||
Name: queryName,
|
Name: queryName,
|
||||||
Series: mergedSeries,
|
Series: mergedSeries,
|
||||||
}
|
}
|
||||||
// Cache the seriesList for future queries
|
// Cache the seriesList for future queries
|
||||||
if len(missedSeries) > 0 && !params.NoCache && q.cache != nil {
|
if len(missedSeries) > 0 && !params.NoCache && q.cache != nil && marshallingErr == nil {
|
||||||
mergedSeriesData, err := json.Marshal(mergedSeries)
|
|
||||||
if err != nil {
|
|
||||||
zap.L().Error("error marshalling merged series", zap.Error(err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = q.cache.Store(cacheKey, mergedSeriesData, time.Hour)
|
err = q.cache.Store(cacheKey, mergedSeriesData, time.Hour)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zap.L().Error("error storing merged series", zap.Error(err))
|
zap.L().Error("error storing merged series", zap.Error(err))
|
||||||
|
@ -241,6 +241,19 @@ func labelsToString(labels map[string]string) string {
|
|||||||
return fmt.Sprintf("{%s}", strings.Join(labelKVs, ","))
|
return fmt.Sprintf("{%s}", strings.Join(labelKVs, ","))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func filterCachedPoints(cachedSeries []*v3.Series, start, end int64) {
|
||||||
|
for _, c := range cachedSeries {
|
||||||
|
points := []v3.Point{}
|
||||||
|
for _, p := range c.Points {
|
||||||
|
if p.Timestamp < start || p.Timestamp > end {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
points = append(points, p)
|
||||||
|
}
|
||||||
|
c.Points = points
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func mergeSerieses(cachedSeries, missedSeries []*v3.Series) []*v3.Series {
|
func mergeSerieses(cachedSeries, missedSeries []*v3.Series) []*v3.Series {
|
||||||
// Merge the missed series with the cached series by timestamp
|
// Merge the missed series with the cached series by timestamp
|
||||||
mergedSeries := make([]*v3.Series, 0)
|
mergedSeries := make([]*v3.Series, 0)
|
||||||
|
@ -96,6 +96,7 @@ type Reader interface {
|
|||||||
GetLogAttributeKeys(ctx context.Context, req *v3.FilterAttributeKeyRequest) (*v3.FilterAttributeKeyResponse, error)
|
GetLogAttributeKeys(ctx context.Context, req *v3.FilterAttributeKeyRequest) (*v3.FilterAttributeKeyResponse, error)
|
||||||
GetLogAttributeValues(ctx context.Context, req *v3.FilterAttributeValueRequest) (*v3.FilterAttributeValueResponse, error)
|
GetLogAttributeValues(ctx context.Context, req *v3.FilterAttributeValueRequest) (*v3.FilterAttributeValueResponse, error)
|
||||||
GetLogAggregateAttributes(ctx context.Context, req *v3.AggregateAttributeRequest) (*v3.AggregateAttributeResponse, error)
|
GetLogAggregateAttributes(ctx context.Context, req *v3.AggregateAttributeRequest) (*v3.AggregateAttributeResponse, error)
|
||||||
|
GetUsers(ctx context.Context) ([]model.UserPayload, error)
|
||||||
|
|
||||||
// Connection needed for rules, not ideal but required
|
// Connection needed for rules, not ideal but required
|
||||||
GetConn() clickhouse.Conn
|
GetConn() clickhouse.Conn
|
||||||
|
@ -51,7 +51,6 @@ const (
|
|||||||
|
|
||||||
var SAAS_EVENTS_LIST = map[string]struct{}{
|
var SAAS_EVENTS_LIST = map[string]struct{}{
|
||||||
TELEMETRY_EVENT_NUMBER_OF_SERVICES: {},
|
TELEMETRY_EVENT_NUMBER_OF_SERVICES: {},
|
||||||
TELEMETRY_EVENT_ACTIVE_USER: {},
|
|
||||||
TELEMETRY_EVENT_HEART_BEAT: {},
|
TELEMETRY_EVENT_HEART_BEAT: {},
|
||||||
TELEMETRY_EVENT_LANGUAGE: {},
|
TELEMETRY_EVENT_LANGUAGE: {},
|
||||||
TELEMETRY_EVENT_SERVICE: {},
|
TELEMETRY_EVENT_SERVICE: {},
|
||||||
@ -61,7 +60,7 @@ var SAAS_EVENTS_LIST = map[string]struct{}{
|
|||||||
TELEMETRY_EVENT_DASHBOARDS_ALERTS: {},
|
TELEMETRY_EVENT_DASHBOARDS_ALERTS: {},
|
||||||
TELEMETRY_EVENT_SUCCESSFUL_DASHBOARD_PANEL_QUERY: {},
|
TELEMETRY_EVENT_SUCCESSFUL_DASHBOARD_PANEL_QUERY: {},
|
||||||
TELEMETRY_EVENT_SUCCESSFUL_ALERT_QUERY: {},
|
TELEMETRY_EVENT_SUCCESSFUL_ALERT_QUERY: {},
|
||||||
// TELEMETRY_EVENT_QUERY_RANGE_API: {}, // this event is not part of SAAS_EVENTS_LIST as it may cause too many events to be sent
|
TELEMETRY_EVENT_QUERY_RANGE_API: {},
|
||||||
}
|
}
|
||||||
|
|
||||||
const api_key = "4Gmoa4ixJAUHx2BpJxsjwA1bEfnwEeRz"
|
const api_key = "4Gmoa4ixJAUHx2BpJxsjwA1bEfnwEeRz"
|
||||||
@ -194,10 +193,7 @@ func createTelemetry() {
|
|||||||
|
|
||||||
rand.Seed(time.Now().UnixNano())
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
|
||||||
data := map[string]interface{}{}
|
|
||||||
|
|
||||||
telemetry.SetTelemetryEnabled(constants.IsTelemetryEnabled())
|
telemetry.SetTelemetryEnabled(constants.IsTelemetryEnabled())
|
||||||
telemetry.SendEvent(TELEMETRY_EVENT_HEART_BEAT, data, "", true, false)
|
|
||||||
|
|
||||||
ticker := time.NewTicker(HEART_BEAT_DURATION)
|
ticker := time.NewTicker(HEART_BEAT_DURATION)
|
||||||
activeUserTicker := time.NewTicker(ACTIVE_USER_DURATION)
|
activeUserTicker := time.NewTicker(ACTIVE_USER_DURATION)
|
||||||
@ -291,8 +287,16 @@ func createTelemetry() {
|
|||||||
for key, value := range tsInfo {
|
for key, value := range tsInfo {
|
||||||
data[key] = value
|
data[key] = value
|
||||||
}
|
}
|
||||||
telemetry.SendEvent(TELEMETRY_EVENT_HEART_BEAT, data, "", true, false)
|
|
||||||
|
|
||||||
|
users, apiErr := telemetry.reader.GetUsers(context.Background())
|
||||||
|
if apiErr == nil {
|
||||||
|
for _, user := range users {
|
||||||
|
if user.Email == DEFAULT_CLOUD_EMAIL {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
telemetry.SendEvent(TELEMETRY_EVENT_HEART_BEAT, data, user.Email, true, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
alertsInfo, err := telemetry.reader.GetAlertsInfo(context.Background())
|
alertsInfo, err := telemetry.reader.GetAlertsInfo(context.Background())
|
||||||
if err == nil {
|
if err == nil {
|
||||||
dashboardsInfo, err := telemetry.reader.GetDashboardsInfo(context.Background())
|
dashboardsInfo, err := telemetry.reader.GetDashboardsInfo(context.Background())
|
||||||
@ -317,14 +321,19 @@ func createTelemetry() {
|
|||||||
"tracesSavedViews": savedViewsInfo.TracesSavedViews,
|
"tracesSavedViews": savedViewsInfo.TracesSavedViews,
|
||||||
}
|
}
|
||||||
// send event only if there are dashboards or alerts or channels
|
// send event only if there are dashboards or alerts or channels
|
||||||
if dashboardsInfo.TotalDashboards > 0 || alertsInfo.TotalAlerts > 0 || len(*channels) > 0 || savedViewsInfo.TotalSavedViews > 0 {
|
if (dashboardsInfo.TotalDashboards > 0 || alertsInfo.TotalAlerts > 0 || len(*channels) > 0 || savedViewsInfo.TotalSavedViews > 0) && apiErr == nil {
|
||||||
telemetry.SendEvent(TELEMETRY_EVENT_DASHBOARDS_ALERTS, dashboardsAlertsData, "", true, false)
|
for _, user := range users {
|
||||||
|
if user.Email == DEFAULT_CLOUD_EMAIL {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
telemetry.SendEvent(TELEMETRY_EVENT_DASHBOARDS_ALERTS, dashboardsAlertsData, user.Email, true, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
}
|
||||||
|
if err != nil || apiErr != nil {
|
||||||
telemetry.SendEvent(TELEMETRY_EVENT_DASHBOARDS_ALERTS, map[string]interface{}{"error": err.Error()}, "", true, false)
|
telemetry.SendEvent(TELEMETRY_EVENT_DASHBOARDS_ALERTS, map[string]interface{}{"error": err.Error()}, "", true, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user