Merge pull request #4413 from SigNoz/release/v0.37.1

Release/v0.37.1
This commit is contained in:
Prashant Shahi 2024-01-22 19:54:11 +05:30 committed by GitHub
commit 9de9fb5863
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 123 additions and 53 deletions

View File

@ -146,7 +146,7 @@ services:
condition: on-failure condition: on-failure
query-service: query-service:
image: signoz/query-service:0.37.0 image: signoz/query-service:0.37.1
command: command:
[ [
"-config=/root/config/prometheus.yml", "-config=/root/config/prometheus.yml",
@ -186,7 +186,7 @@ services:
<<: *db-depend <<: *db-depend
frontend: frontend:
image: signoz/frontend:0.37.0 image: signoz/frontend:0.37.1
deploy: deploy:
restart_policy: restart_policy:
condition: on-failure condition: on-failure

View File

@ -164,7 +164,7 @@ services:
# Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md` # Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md`
query-service: query-service:
image: signoz/query-service:${DOCKER_TAG:-0.37.0} image: signoz/query-service:${DOCKER_TAG:-0.37.1}
container_name: signoz-query-service container_name: signoz-query-service
command: command:
[ [
@ -203,7 +203,7 @@ services:
<<: *db-depend <<: *db-depend
frontend: frontend:
image: signoz/frontend:${DOCKER_TAG:-0.37.0} image: signoz/frontend:${DOCKER_TAG:-0.37.1}
container_name: signoz-frontend container_name: signoz-frontend
restart: on-failure restart: on-failure
depends_on: depends_on:

View File

@ -193,7 +193,7 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) {
} }
// start the usagemanager // start the usagemanager
usageManager, err := usage.New("sqlite", localDB, lm.GetRepo(), reader.GetConn()) usageManager, err := usage.New("sqlite", modelDao, lm.GetRepo(), reader.GetConn())
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -20,6 +20,8 @@ type Usage struct {
TimeStamp time.Time `json:"timestamp"` TimeStamp time.Time `json:"timestamp"`
Count int64 `json:"count"` Count int64 `json:"count"`
Size int64 `json:"size"` Size int64 `json:"size"`
OrgName string `json:"orgName"`
TenantId string `json:"tenantId"`
} }
type UsageDB struct { type UsageDB struct {

View File

@ -4,6 +4,8 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"os"
"regexp"
"strings" "strings"
"sync/atomic" "sync/atomic"
"time" "time"
@ -11,10 +13,10 @@ import (
"github.com/ClickHouse/clickhouse-go/v2" "github.com/ClickHouse/clickhouse-go/v2"
"github.com/go-co-op/gocron" "github.com/go-co-op/gocron"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/jmoiron/sqlx"
"go.uber.org/zap" "go.uber.org/zap"
"go.signoz.io/signoz/ee/query-service/dao"
licenseserver "go.signoz.io/signoz/ee/query-service/integrations/signozio" licenseserver "go.signoz.io/signoz/ee/query-service/integrations/signozio"
"go.signoz.io/signoz/ee/query-service/license" "go.signoz.io/signoz/ee/query-service/license"
"go.signoz.io/signoz/ee/query-service/model" "go.signoz.io/signoz/ee/query-service/model"
@ -38,15 +40,29 @@ type Manager struct {
licenseRepo *license.Repo licenseRepo *license.Repo
scheduler *gocron.Scheduler scheduler *gocron.Scheduler
modelDao dao.ModelDao
tenantID string
} }
func New(dbType string, db *sqlx.DB, licenseRepo *license.Repo, clickhouseConn clickhouse.Conn) (*Manager, error) { func New(dbType string, modelDao dao.ModelDao, licenseRepo *license.Repo, clickhouseConn clickhouse.Conn) (*Manager, error) {
hostNameRegex := regexp.MustCompile(`tcp://(?P<hostname>.*):`)
hostNameRegexMatches := hostNameRegex.FindStringSubmatch(os.Getenv("ClickHouseUrl"))
tenantID := ""
if len(hostNameRegexMatches) == 2 {
tenantID = hostNameRegexMatches[1]
tenantID = strings.TrimRight(tenantID, "-clickhouse")
}
m := &Manager{ m := &Manager{
// repository: repo, // repository: repo,
clickhouseConn: clickhouseConn, clickhouseConn: clickhouseConn,
licenseRepo: licenseRepo, licenseRepo: licenseRepo,
scheduler: gocron.NewScheduler(time.UTC).Every(1).Day().At("00:00"), // send usage every at 00:00 UTC scheduler: gocron.NewScheduler(time.UTC).Every(1).Day().At("00:00"), // send usage every at 00:00 UTC
modelDao: modelDao,
tenantID: tenantID,
} }
return m, nil return m, nil
} }
@ -123,6 +139,19 @@ func (lm *Manager) UploadUsage() {
zap.S().Info("uploading usage data") zap.S().Info("uploading usage data")
// Try to get the org name
orgName := ""
orgNames, err := lm.modelDao.GetOrgs(ctx)
if err != nil {
zap.S().Errorf("failed to get org data: %v", zap.Error(err))
} else {
if len(orgNames) != 1 {
zap.S().Errorf("expected one org but got %d orgs", len(orgNames))
} else {
orgName = orgNames[0].Name
}
}
usagesPayload := []model.Usage{} usagesPayload := []model.Usage{}
for _, usage := range usages { for _, usage := range usages {
usageDataBytes, err := encryption.Decrypt([]byte(usage.ExporterID[:32]), []byte(usage.Data)) usageDataBytes, err := encryption.Decrypt([]byte(usage.ExporterID[:32]), []byte(usage.Data))
@ -142,6 +171,8 @@ func (lm *Manager) UploadUsage() {
usageData.ExporterID = usage.ExporterID usageData.ExporterID = usage.ExporterID
usageData.Type = usage.Type usageData.Type = usage.Type
usageData.Tenant = usage.Tenant usageData.Tenant = usage.Tenant
usageData.OrgName = orgName
usageData.TenantId = lm.tenantID
usagesPayload = append(usagesPayload, usageData) usagesPayload = append(usagesPayload, usageData)
} }

View File

@ -8,6 +8,7 @@ export const Layout = styled(LayoutComponent)`
min-height: calc(100vh - 8rem); min-height: calc(100vh - 8rem);
overflow: hidden; overflow: hidden;
height: 100%; height: 100%;
flex-direction: column !important;
} }
`; `;

View File

@ -18,13 +18,14 @@ import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariab
import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartOptions'; import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartOptions';
import { getUPlotChartData } from 'lib/uPlotLib/utils/getUplotChartData'; import { getUPlotChartData } from 'lib/uPlotLib/utils/getUplotChartData';
import { useDashboard } from 'providers/Dashboard/Dashboard'; import { useDashboard } from 'providers/Dashboard/Dashboard';
import { useCallback, useEffect, useRef, useState } from 'react'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
import uPlot from 'uplot'; import uPlot from 'uplot';
import { getTimeRange } from 'utils/getTimeRange'; import { getTimeRange } from 'utils/getTimeRange';
import { getGraphVisibilityStateOnDataChange } from '../utils';
import { PANEL_TYPES_VS_FULL_VIEW_TABLE } from './contants'; import { PANEL_TYPES_VS_FULL_VIEW_TABLE } from './contants';
import GraphManager from './GraphManager'; import GraphManager from './GraphManager';
// import GraphManager from './GraphManager'; // import GraphManager from './GraphManager';
@ -36,13 +37,14 @@ function FullView({
fullViewOptions = true, fullViewOptions = true,
onClickHandler, onClickHandler,
name, name,
originalName,
yAxisUnit, yAxisUnit,
options,
onDragSelect, onDragSelect,
isDependedDataLoaded = false, isDependedDataLoaded = false,
graphsVisibilityStates,
onToggleModelHandler, onToggleModelHandler,
parentChartRef, parentChartRef,
setGraphsVisibilityStates, parentGraphVisibilityState,
}: FullViewProps): JSX.Element { }: FullViewProps): JSX.Element {
const { selectedTime: globalSelectedTime } = useSelector< const { selectedTime: globalSelectedTime } = useSelector<
AppState, AppState,
@ -55,6 +57,20 @@ function FullView({
const { selectedDashboard, isDashboardLocked } = useDashboard(); const { selectedDashboard, isDashboardLocked } = useDashboard();
const { graphVisibilityStates: localStoredVisibilityStates } = useMemo(
() =>
getGraphVisibilityStateOnDataChange({
options,
isExpandedName: false,
name: originalName,
}),
[options, originalName],
);
const [graphsVisibilityStates, setGraphsVisibilityStates] = useState(
localStoredVisibilityStates,
);
const getSelectedTime = useCallback( const getSelectedTime = useCallback(
() => () =>
timeItems.find((e) => e.enum === (widget?.timePreferance || 'GLOBAL_TIME')), timeItems.find((e) => e.enum === (widget?.timePreferance || 'GLOBAL_TIME')),
@ -144,9 +160,9 @@ function FullView({
useEffect(() => { useEffect(() => {
graphsVisibilityStates?.forEach((e, i) => { graphsVisibilityStates?.forEach((e, i) => {
fullViewChartRef?.current?.toggleGraph(i, e); fullViewChartRef?.current?.toggleGraph(i, e);
parentChartRef?.current?.toggleGraph(i, e);
}); });
}, [graphsVisibilityStates, parentChartRef]); parentGraphVisibilityState(graphsVisibilityStates);
}, [graphsVisibilityStates, parentGraphVisibilityState]);
if (response.isFetching) { if (response.isFetching) {
return <Spinner height="100%" size="large" tip="Loading..." />; return <Spinner height="100%" size="large" tip="Loading..." />;
@ -206,7 +222,7 @@ function FullView({
{canModifyChart && chartOptions && !isDashboardLocked && ( {canModifyChart && chartOptions && !isDashboardLocked && (
<GraphManager <GraphManager
data={chartData} data={chartData}
name={name} name={originalName}
options={chartOptions} options={chartOptions}
yAxisUnit={yAxisUnit} yAxisUnit={yAxisUnit}
onToggleModelHandler={onToggleModelHandler} onToggleModelHandler={onToggleModelHandler}

View File

@ -50,13 +50,14 @@ export interface FullViewProps {
fullViewOptions?: boolean; fullViewOptions?: boolean;
onClickHandler?: OnClickPluginOpts['onClick']; onClickHandler?: OnClickPluginOpts['onClick'];
name: string; name: string;
originalName: string;
options: uPlot.Options;
yAxisUnit?: string; yAxisUnit?: string;
onDragSelect: (start: number, end: number) => void; onDragSelect: (start: number, end: number) => void;
isDependedDataLoaded?: boolean; isDependedDataLoaded?: boolean;
graphsVisibilityStates?: boolean[];
onToggleModelHandler?: GraphManagerProps['onToggleModelHandler']; onToggleModelHandler?: GraphManagerProps['onToggleModelHandler'];
setGraphsVisibilityStates: Dispatch<SetStateAction<boolean[]>>;
parentChartRef: GraphManagerProps['lineChartRef']; parentChartRef: GraphManagerProps['lineChartRef'];
parentGraphVisibilityState: Dispatch<SetStateAction<boolean[]>>;
} }
export interface GraphManagerProps extends UplotProps { export interface GraphManagerProps extends UplotProps {
@ -64,8 +65,8 @@ export interface GraphManagerProps extends UplotProps {
yAxisUnit?: string; yAxisUnit?: string;
onToggleModelHandler?: () => void; onToggleModelHandler?: () => void;
options: uPlot.Options; options: uPlot.Options;
setGraphsVisibilityStates: FullViewProps['setGraphsVisibilityStates']; graphsVisibilityStates?: boolean[];
graphsVisibilityStates: FullViewProps['graphsVisibilityStates']; setGraphsVisibilityStates: Dispatch<SetStateAction<boolean[]>>;
lineChartRef?: MutableRefObject<ToggleGraphProps | undefined>; lineChartRef?: MutableRefObject<ToggleGraphProps | undefined>;
parentChartRef?: MutableRefObject<ToggleGraphProps | undefined>; parentChartRef?: MutableRefObject<ToggleGraphProps | undefined>;
} }

View File

@ -17,7 +17,6 @@ import {
SetStateAction, SetStateAction,
useCallback, useCallback,
useEffect, useEffect,
useMemo,
useRef, useRef,
useState, useState,
} from 'react'; } from 'react';
@ -39,14 +38,15 @@ function WidgetGraphComponent({
queryResponse, queryResponse,
errorMessage, errorMessage,
name, name,
onClickHandler,
threshold, threshold,
headerMenuList, headerMenuList,
isWarning, isWarning,
data, data,
options, options,
graphVisibiltyState,
onClickHandler,
onDragSelect, onDragSelect,
graphVisibility, setGraphVisibility,
}: WidgetGraphComponentProps): JSX.Element { }: WidgetGraphComponentProps): JSX.Element {
const [deleteModal, setDeleteModal] = useState(false); const [deleteModal, setDeleteModal] = useState(false);
const [hovered, setHovered] = useState(false); const [hovered, setHovered] = useState(false);
@ -60,33 +60,28 @@ function WidgetGraphComponent({
const lineChartRef = useRef<ToggleGraphProps>(); const lineChartRef = useRef<ToggleGraphProps>();
const graphRef = useRef<HTMLDivElement>(null); const graphRef = useRef<HTMLDivElement>(null);
const { graphVisibilityStates: localStoredVisibilityStates } = useMemo( useEffect(() => {
() => if (queryResponse.isSuccess) {
getGraphVisibilityStateOnDataChange({ const {
graphVisibilityStates: localStoredVisibilityState,
} = getGraphVisibilityStateOnDataChange({
options, options,
isExpandedName: true, isExpandedName: false,
name, name,
}), });
[options, name], setGraphVisibility(localStoredVisibilityState);
); }
// eslint-disable-next-line react-hooks/exhaustive-deps
const [graphsVisibilityStates, setGraphsVisibilityStates] = useState< }, [queryResponse.isSuccess]);
boolean[]
>(localStoredVisibilityStates);
useEffect(() => { useEffect(() => {
setGraphsVisibilityStates(localStoredVisibilityStates);
if (!lineChartRef.current) return; if (!lineChartRef.current) return;
localStoredVisibilityStates.forEach((state, index) => { graphVisibiltyState.forEach((state, index) => {
lineChartRef.current?.toggleGraph(index, state);
});
setGraphsVisibilityStates(localStoredVisibilityStates);
}, [localStoredVisibilityStates]);
graphVisibility?.forEach((state, index) => {
lineChartRef.current?.toggleGraph(index, state); lineChartRef.current?.toggleGraph(index, state);
}); });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const { setLayouts, selectedDashboard, setSelectedDashboard } = useDashboard(); const { setLayouts, selectedDashboard, setSelectedDashboard } = useDashboard();
@ -279,13 +274,14 @@ function WidgetGraphComponent({
> >
<FullView <FullView
name={`${name}expanded`} name={`${name}expanded`}
originalName={name}
widget={widget} widget={widget}
yAxisUnit={widget.yAxisUnit} yAxisUnit={widget.yAxisUnit}
onToggleModelHandler={onToggleModelHandler} onToggleModelHandler={onToggleModelHandler}
parentChartRef={lineChartRef} parentChartRef={lineChartRef}
parentGraphVisibilityState={setGraphVisibility}
onDragSelect={onDragSelect} onDragSelect={onDragSelect}
setGraphsVisibilityStates={setGraphsVisibilityStates} options={options}
graphsVisibilityStates={graphsVisibilityStates}
/> />
</Modal> </Modal>

View File

@ -167,13 +167,6 @@ function GridCardGraph({
Array(queryResponse.data?.payload?.data.result.length || 0).fill(true), Array(queryResponse.data?.payload?.data.result.length || 0).fill(true),
); );
useEffect(() => {
setGraphVisibility([
true,
...Array(queryResponse.data?.payload?.data.result.length).fill(true),
]);
}, [queryResponse.data?.payload?.data.result.length]);
const options = useMemo( const options = useMemo(
() => () =>
getUPlotChartOptions({ getUPlotChartOptions({
@ -227,7 +220,8 @@ function GridCardGraph({
threshold={threshold} threshold={threshold}
headerMenuList={menuList} headerMenuList={menuList}
onClickHandler={onClickHandler} onClickHandler={onClickHandler}
graphVisibility={graphVisibility} graphVisibiltyState={graphVisibility}
setGraphVisibility={setGraphVisibility}
/> />
)} )}
</div> </div>

View File

@ -1,7 +1,7 @@
import { ToggleGraphProps } from 'components/Graph/types'; import { ToggleGraphProps } from 'components/Graph/types';
import { UplotProps } from 'components/Uplot/Uplot'; import { UplotProps } from 'components/Uplot/Uplot';
import { OnClickPluginOpts } from 'lib/uPlotLib/plugins/onClickPlugin'; import { OnClickPluginOpts } from 'lib/uPlotLib/plugins/onClickPlugin';
import { MutableRefObject, ReactNode } from 'react'; import { Dispatch, MutableRefObject, ReactNode, SetStateAction } from 'react';
import { UseQueryResult } from 'react-query'; import { UseQueryResult } from 'react-query';
import { ErrorResponse, SuccessResponse } from 'types/api'; import { ErrorResponse, SuccessResponse } from 'types/api';
import { Dashboard, Widgets } from 'types/api/dashboard/getAll'; import { Dashboard, Widgets } from 'types/api/dashboard/getAll';
@ -28,7 +28,8 @@ export interface WidgetGraphComponentProps extends UplotProps {
threshold?: ReactNode; threshold?: ReactNode;
headerMenuList: MenuItemKeys[]; headerMenuList: MenuItemKeys[];
isWarning: boolean; isWarning: boolean;
graphVisibility?: boolean[]; graphVisibiltyState: boolean[];
setGraphVisibility: Dispatch<SetStateAction<boolean[]>>;
} }
export interface GridCardGraphProps { export interface GridCardGraphProps {

View File

@ -122,8 +122,17 @@ export function replaceStringWithMaxLength(
if (lastSearchValue === '') { if (lastSearchValue === '') {
return `${mainString}${replacementString},`; return `${mainString}${replacementString},`;
} }
/**
* We need to escape the special characters in the lastSearchValue else the
* new RegExp fails with error range out of order in char class
*/
const escapedLastSearchValue = lastSearchValue.replace(
/[-/\\^$*+?.()|[\]{}]/g,
'\\$&',
);
const updatedString = mainString.replace( const updatedString = mainString.replace(
new RegExp(`${lastSearchValue}(?=[^${lastSearchValue}]*$)`), new RegExp(`${escapedLastSearchValue}(?=[^${escapedLastSearchValue}]*$)`),
replacementString, replacementString,
); );
return `${updatedString},`; return `${updatedString},`;

View File

@ -279,6 +279,18 @@ function DateTimeSelection({
setRefreshButtonHidden(updatedTime === 'custom'); setRefreshButtonHidden(updatedTime === 'custom');
updateTimeInterval(updatedTime, [preStartTime, preEndTime]); updateTimeInterval(updatedTime, [preStartTime, preEndTime]);
if (updatedTime !== 'custom') {
const { minTime, maxTime } = GetMinMax(updatedTime);
urlQuery.set(QueryParams.startTime, minTime.toString());
urlQuery.set(QueryParams.endTime, maxTime.toString());
} else {
urlQuery.set(QueryParams.startTime, preStartTime.toString());
urlQuery.set(QueryParams.endTime, preEndTime.toString());
}
const generatedUrl = `${location.pathname}?${urlQuery.toString()}`;
history.replace(generatedUrl);
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [location.pathname, updateTimeInterval, globalTimeLoading]); }, [location.pathname, updateTimeInterval, globalTimeLoading]);

View File

@ -25,6 +25,7 @@ import {
parseQueryIntoPageSize, parseQueryIntoPageSize,
parseQueryIntoSelectedTags, parseQueryIntoSelectedTags,
parseSelectedFilter, parseSelectedFilter,
stripTimestampsFromQuery,
} from './util'; } from './util';
export const GetInitialTraceFilter = ( export const GetInitialTraceFilter = (
@ -113,8 +114,11 @@ export const GetInitialTraceFilter = (
); );
if (response.payload && !isSelectionSkipped.currentValue) { if (response.payload && !isSelectionSkipped.currentValue) {
/** this is required as now we have timestamps updated in date time selection component
* so for initial filters we need to strip timestamps and check for initial load
*/
const diff = const diff =
query.length === 0 stripTimestampsFromQuery(query).length === 0
? traces.filterToFetchData ? traces.filterToFetchData
: xor(traces.filterToFetchData, getFilterToFetchData.currentValue); : xor(traces.filterToFetchData, getFilterToFetchData.currentValue);

View File

@ -86,3 +86,6 @@ export const getFilter = (data: GetFilterPayload): TraceReducer['filter'] => {
return filter; return filter;
}; };
export const stripTimestampsFromQuery = (query: string): string =>
query.replace(/(\?|&)startTime=\d+/, '').replace(/&endTime=\d+/, '');