mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-14 04:26:02 +08:00
parent
5bfc2af51b
commit
3968f11b3d
@ -42,8 +42,9 @@ export interface Option {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const ServiceMapOptions: Option[] = [
|
export const ServiceMapOptions: Option[] = [
|
||||||
{ value: '1min', label: 'Last 1 min' },
|
|
||||||
{ value: '5min', label: 'Last 5 min' },
|
{ value: '5min', label: 'Last 5 min' },
|
||||||
|
{ value: '15min', label: 'Last 15 min' },
|
||||||
|
{ value: '30min', label: 'Last 30 min' },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const getDefaultOption = (route: string): Time => {
|
export const getDefaultOption = (route: string): Time => {
|
||||||
|
@ -45,6 +45,9 @@ interface graphLink {
|
|||||||
source: string;
|
source: string;
|
||||||
target: string;
|
target: string;
|
||||||
value: number;
|
value: number;
|
||||||
|
callRate: number;
|
||||||
|
errorRate: number;
|
||||||
|
p99: number;
|
||||||
}
|
}
|
||||||
export interface graphDataType {
|
export interface graphDataType {
|
||||||
nodes: graphNode[];
|
nodes: graphNode[];
|
||||||
@ -96,16 +99,16 @@ function ServiceMap(props: ServiceMapProps): JSX.Element {
|
|||||||
const graphData = { nodes, links };
|
const graphData = { nodes, links };
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<SelectService
|
{/* <SelectService
|
||||||
services={serviceMap.services}
|
services={serviceMap.items}
|
||||||
zoomToService={zoomToService}
|
zoomToService={zoomToService}
|
||||||
zoomToDefault={zoomToDefault}
|
zoomToDefault={zoomToDefault}
|
||||||
/>
|
/> */}
|
||||||
<ForceGraph2D
|
<ForceGraph2D
|
||||||
ref={fgRef}
|
ref={fgRef}
|
||||||
cooldownTicks={100}
|
cooldownTicks={100}
|
||||||
graphData={graphData}
|
graphData={graphData}
|
||||||
nodeLabel={getTooltip}
|
linkLabel={getTooltip}
|
||||||
linkAutoColorBy={(d) => d.target}
|
linkAutoColorBy={(d) => d.target}
|
||||||
linkDirectionalParticles="value"
|
linkDirectionalParticles="value"
|
||||||
linkDirectionalParticleSpeed={(d) => d.value}
|
linkDirectionalParticleSpeed={(d) => d.value}
|
||||||
@ -124,7 +127,7 @@ function ServiceMap(props: ServiceMapProps): JSX.Element {
|
|||||||
ctx.fillStyle = isDarkMode ? '#ffffff' : '#000000';
|
ctx.fillStyle = isDarkMode ? '#ffffff' : '#000000';
|
||||||
ctx.fillText(label, node.x, node.y);
|
ctx.fillText(label, node.x, node.y);
|
||||||
}}
|
}}
|
||||||
onNodeClick={(node) => {
|
onLinkHover={(node) => {
|
||||||
const tooltip = document.querySelector('.graph-tooltip');
|
const tooltip = document.querySelector('.graph-tooltip');
|
||||||
if (tooltip && node) {
|
if (tooltip && node) {
|
||||||
tooltip.innerHTML = getTooltip(node);
|
tooltip.innerHTML = getTooltip(node);
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
/*eslint-disable*/
|
/*eslint-disable*/
|
||||||
//@ts-nocheck
|
//@ts-nocheck
|
||||||
|
|
||||||
import { cloneDeep, find, maxBy, uniq, uniqBy } from 'lodash-es';
|
import { cloneDeep, find, maxBy, uniq, uniqBy, groupBy, sumBy } from 'lodash-es';
|
||||||
import { graphDataType } from './ServiceMap';
|
import { graphDataType } from './ServiceMap';
|
||||||
|
|
||||||
const MIN_WIDTH = 10;
|
const MIN_WIDTH = 10;
|
||||||
const MAX_WIDTH = 20;
|
const MAX_WIDTH = 20;
|
||||||
const DEFAULT_FONT_SIZE = 6;
|
const DEFAULT_FONT_SIZE = 6;
|
||||||
|
|
||||||
export const getDimensions = (num, highest) => {
|
export const getDimensions = (num, highest) => {
|
||||||
const percentage = (num / highest) * 100;
|
const percentage = (num / highest) * 100;
|
||||||
const width = (percentage * (MAX_WIDTH - MIN_WIDTH)) / 100 + MIN_WIDTH;
|
const width = (percentage * (MAX_WIDTH - MIN_WIDTH)) / 100 + MIN_WIDTH;
|
||||||
@ -18,19 +19,30 @@ export const getDimensions = (num, highest) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getGraphData = (serviceMap, isDarkMode): graphDataType => {
|
export const getGraphData = (serviceMap, isDarkMode): graphDataType => {
|
||||||
const { items, services } = serviceMap;
|
const { items } = serviceMap;
|
||||||
|
const services = Object.values(groupBy(items, 'child')).map((e) => {
|
||||||
|
return {
|
||||||
|
serviceName: e[0].child,
|
||||||
|
errorRate: sumBy(e, 'errorRate'),
|
||||||
|
callRate: sumBy(e, 'callRate'),
|
||||||
|
}
|
||||||
|
});
|
||||||
const highestCallCount = maxBy(items, (e) => e?.callCount)?.callCount;
|
const highestCallCount = maxBy(items, (e) => e?.callCount)?.callCount;
|
||||||
const highestCallRate = maxBy(services, (e) => e?.callRate)?.callRate;
|
const highestCallRate = maxBy(services, (e) => e?.callRate)?.callRate;
|
||||||
|
|
||||||
const divNum = Number(
|
const divNum = Number(
|
||||||
String(1).padEnd(highestCallCount.toString().length, '0'),
|
String(1).padEnd(highestCallCount.toString().length, '0'),
|
||||||
);
|
);
|
||||||
|
|
||||||
const links = cloneDeep(items).map((node) => {
|
const links = cloneDeep(items).map((node) => {
|
||||||
const { parent, child, callCount } = node;
|
const { parent, child, callCount, callRate, errorRate, p99 } = node;
|
||||||
return {
|
return {
|
||||||
source: parent,
|
source: parent,
|
||||||
target: child,
|
target: child,
|
||||||
value: (100 - callCount / divNum) * 0.03,
|
value: (100 - callCount / divNum) * 0.03,
|
||||||
|
callRate,
|
||||||
|
errorRate,
|
||||||
|
p99,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
const uniqParent = uniqBy(cloneDeep(items), 'parent').map((e) => e.parent);
|
const uniqParent = uniqBy(cloneDeep(items), 'parent').map((e) => e.parent);
|
||||||
@ -47,15 +59,10 @@ export const getGraphData = (serviceMap, isDarkMode): graphDataType => {
|
|||||||
width: MIN_WIDTH,
|
width: MIN_WIDTH,
|
||||||
color,
|
color,
|
||||||
nodeVal: MIN_WIDTH,
|
nodeVal: MIN_WIDTH,
|
||||||
callRate: 0,
|
|
||||||
errorRate: 0,
|
|
||||||
p99: 0,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (service.errorRate > 0) {
|
if (service.errorRate > 0) {
|
||||||
color = isDarkMode ? '#DB836E' : '#F98989';
|
color = isDarkMode ? '#DB836E' : '#F98989';
|
||||||
} else if (service.fourXXRate > 0) {
|
|
||||||
color = isDarkMode ? '#C79931' : '#F9DA7B';
|
|
||||||
}
|
}
|
||||||
const { fontSize, width } = getDimensions(service.callRate, highestCallRate);
|
const { fontSize, width } = getDimensions(service.callRate, highestCallRate);
|
||||||
return {
|
return {
|
||||||
@ -65,9 +72,6 @@ export const getGraphData = (serviceMap, isDarkMode): graphDataType => {
|
|||||||
width,
|
width,
|
||||||
color,
|
color,
|
||||||
nodeVal: width,
|
nodeVal: width,
|
||||||
callRate: service.callRate.toFixed(2),
|
|
||||||
errorRate: service.errorRate,
|
|
||||||
p99: service.p99,
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
@ -90,25 +94,31 @@ export const getZoomPx = (): number => {
|
|||||||
return 190;
|
return 190;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getTooltip = (node: {
|
const getRound2DigitsAfterDecimal = (num: number) => {
|
||||||
|
if (num === 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return num.toFixed(20).match(/^-?\d*\.?0*\d{0,2}/)[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getTooltip = (link: {
|
||||||
p99: number;
|
p99: number;
|
||||||
errorRate: number;
|
errorRate: number;
|
||||||
callRate: number;
|
callRate: number;
|
||||||
id: string;
|
id: string;
|
||||||
}) => {
|
}) => {
|
||||||
return `<div style="color:#333333;padding:12px;background: white;border-radius: 2px;">
|
return `<div style="color:#333333;padding:12px;background: white;border-radius: 2px;">
|
||||||
<div style="font-weight:bold; margin-bottom:16px;">${node.id}</div>
|
|
||||||
<div class="keyval">
|
<div class="keyval">
|
||||||
<div class="key">P99 latency:</div>
|
<div class="key">P99 latency:</div>
|
||||||
<div class="val">${node.p99 / 1000000}ms</div>
|
<div class="val">${getRound2DigitsAfterDecimal(link.p99/ 1000000)}ms</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="keyval">
|
<div class="keyval">
|
||||||
<div class="key">Request:</div>
|
<div class="key">Request:</div>
|
||||||
<div class="val">${node.callRate}/sec</div>
|
<div class="val">${getRound2DigitsAfterDecimal(link.callRate)}/sec</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="keyval">
|
<div class="keyval">
|
||||||
<div class="key">Error Rate:</div>
|
<div class="key">Error Rate:</div>
|
||||||
<div class="val">${node.errorRate}%</div>
|
<div class="val">${getRound2DigitsAfterDecimal(link.errorRate)}%</div>
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
};
|
};
|
||||||
|
@ -6,26 +6,16 @@ import { ActionTypes } from './types';
|
|||||||
|
|
||||||
export interface ServiceMapStore {
|
export interface ServiceMapStore {
|
||||||
items: ServicesMapItem[];
|
items: ServicesMapItem[];
|
||||||
services: ServicesItem[];
|
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ServicesItem {
|
|
||||||
serviceName: string;
|
|
||||||
p99: number;
|
|
||||||
avgDuration: number;
|
|
||||||
numCalls: number;
|
|
||||||
callRate: number;
|
|
||||||
numErrors: number;
|
|
||||||
errorRate: number;
|
|
||||||
num4XX: number;
|
|
||||||
fourXXRate: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ServicesMapItem {
|
export interface ServicesMapItem {
|
||||||
parent: string;
|
parent: string;
|
||||||
child: string;
|
child: string;
|
||||||
callCount: number;
|
callCount: number;
|
||||||
|
callRate: number;
|
||||||
|
errorRate: number;
|
||||||
|
p99: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ServiceMapItemAction {
|
export interface ServiceMapItemAction {
|
||||||
@ -33,11 +23,6 @@ export interface ServiceMapItemAction {
|
|||||||
payload: ServicesMapItem[];
|
payload: ServicesMapItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ServicesAction {
|
|
||||||
type: ActionTypes.getServices;
|
|
||||||
payload: ServicesItem[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ServiceMapLoading {
|
export interface ServiceMapLoading {
|
||||||
type: ActionTypes.serviceMapLoading;
|
type: ActionTypes.serviceMapLoading;
|
||||||
payload: {
|
payload: {
|
||||||
@ -55,19 +40,13 @@ export const getDetailedServiceMapItems = (globalTime: GlobalTime) => {
|
|||||||
end,
|
end,
|
||||||
tags: [],
|
tags: [],
|
||||||
};
|
};
|
||||||
const [serviceMapDependenciesResponse, response] = await Promise.all([
|
const [dependencyGraphResponse] = await Promise.all([
|
||||||
api.post<ServicesMapItem[]>(`/serviceMapDependencies`, serviceMapPayload),
|
api.post<ServicesMapItem[]>(`/dependency_graph`, serviceMapPayload),
|
||||||
api.post<ServicesItem[]>(`/services`, serviceMapPayload),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
dispatch<ServicesAction>({
|
|
||||||
type: ActionTypes.getServices,
|
|
||||||
payload: response.data,
|
|
||||||
});
|
|
||||||
|
|
||||||
dispatch<ServiceMapItemAction>({
|
dispatch<ServiceMapItemAction>({
|
||||||
type: ActionTypes.getServiceMapItems,
|
type: ActionTypes.getServiceMapItems,
|
||||||
payload: serviceMapDependenciesResponse.data,
|
payload: dependencyGraphResponse.data,
|
||||||
});
|
});
|
||||||
|
|
||||||
dispatch<ServiceMapLoading>({
|
dispatch<ServiceMapLoading>({
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
import {
|
import { ServiceMapItemAction, ServiceMapLoading } from './serviceMap';
|
||||||
ServiceMapItemAction,
|
|
||||||
ServiceMapLoading,
|
|
||||||
ServicesAction,
|
|
||||||
} from './serviceMap';
|
|
||||||
import { GetUsageDataAction } from './usage';
|
import { GetUsageDataAction } from './usage';
|
||||||
|
|
||||||
export enum ActionTypes {
|
export enum ActionTypes {
|
||||||
@ -17,6 +13,5 @@ export enum ActionTypes {
|
|||||||
|
|
||||||
export type Action =
|
export type Action =
|
||||||
| GetUsageDataAction
|
| GetUsageDataAction
|
||||||
| ServicesAction
|
|
||||||
| ServiceMapItemAction
|
| ServiceMapItemAction
|
||||||
| ServiceMapLoading;
|
| ServiceMapLoading;
|
||||||
|
@ -2,7 +2,6 @@ import { Action, ActionTypes, ServiceMapStore } from 'store/actions';
|
|||||||
|
|
||||||
const initialState: ServiceMapStore = {
|
const initialState: ServiceMapStore = {
|
||||||
items: [],
|
items: [],
|
||||||
services: [],
|
|
||||||
loading: true,
|
loading: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -16,11 +15,6 @@ export const ServiceMapReducer = (
|
|||||||
...state,
|
...state,
|
||||||
items: action.payload,
|
items: action.payload,
|
||||||
};
|
};
|
||||||
case ActionTypes.getServices:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
services: action.payload,
|
|
||||||
};
|
|
||||||
case ActionTypes.serviceMapLoading: {
|
case ActionTypes.serviceMapLoading: {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
@ -25,6 +25,7 @@ const (
|
|||||||
defaultErrorTable string = "signoz_error_index_v2"
|
defaultErrorTable string = "signoz_error_index_v2"
|
||||||
defaultDurationTable string = "durationSortMV"
|
defaultDurationTable string = "durationSortMV"
|
||||||
defaultSpansTable string = "signoz_spans"
|
defaultSpansTable string = "signoz_spans"
|
||||||
|
defaultDependencyGraphTable string = "dependency_graph_minutes"
|
||||||
defaultTopLevelOperationsTable string = "top_level_operations"
|
defaultTopLevelOperationsTable string = "top_level_operations"
|
||||||
defaultWriteBatchDelay time.Duration = 5 * time.Second
|
defaultWriteBatchDelay time.Duration = 5 * time.Second
|
||||||
defaultWriteBatchSize int = 10000
|
defaultWriteBatchSize int = 10000
|
||||||
@ -53,6 +54,7 @@ type namespaceConfig struct {
|
|||||||
DurationTable string
|
DurationTable string
|
||||||
SpansTable string
|
SpansTable string
|
||||||
ErrorTable string
|
ErrorTable string
|
||||||
|
DependencyGraphTable string
|
||||||
TopLevelOperationsTable string
|
TopLevelOperationsTable string
|
||||||
WriteBatchDelay time.Duration
|
WriteBatchDelay time.Duration
|
||||||
WriteBatchSize int
|
WriteBatchSize int
|
||||||
@ -113,6 +115,7 @@ func NewOptions(datasource string, primaryNamespace string, otherNamespaces ...s
|
|||||||
ErrorTable: defaultErrorTable,
|
ErrorTable: defaultErrorTable,
|
||||||
DurationTable: defaultDurationTable,
|
DurationTable: defaultDurationTable,
|
||||||
SpansTable: defaultSpansTable,
|
SpansTable: defaultSpansTable,
|
||||||
|
DependencyGraphTable: defaultDependencyGraphTable,
|
||||||
TopLevelOperationsTable: defaultTopLevelOperationsTable,
|
TopLevelOperationsTable: defaultTopLevelOperationsTable,
|
||||||
WriteBatchDelay: defaultWriteBatchDelay,
|
WriteBatchDelay: defaultWriteBatchDelay,
|
||||||
WriteBatchSize: defaultWriteBatchSize,
|
WriteBatchSize: defaultWriteBatchSize,
|
||||||
|
@ -83,6 +83,7 @@ type ClickHouseReader struct {
|
|||||||
indexTable string
|
indexTable string
|
||||||
errorTable string
|
errorTable string
|
||||||
spansTable string
|
spansTable string
|
||||||
|
dependencyGraphTable string
|
||||||
topLevelOperationsTable string
|
topLevelOperationsTable string
|
||||||
queryEngine *promql.Engine
|
queryEngine *promql.Engine
|
||||||
remoteStorage *remote.Storage
|
remoteStorage *remote.Storage
|
||||||
@ -121,6 +122,7 @@ func NewReader(localDB *sqlx.DB, configFile string) *ClickHouseReader {
|
|||||||
errorTable: options.primary.ErrorTable,
|
errorTable: options.primary.ErrorTable,
|
||||||
durationTable: options.primary.DurationTable,
|
durationTable: options.primary.DurationTable,
|
||||||
spansTable: options.primary.SpansTable,
|
spansTable: options.primary.SpansTable,
|
||||||
|
dependencyGraphTable: options.primary.DependencyGraphTable,
|
||||||
topLevelOperationsTable: options.primary.TopLevelOperationsTable,
|
topLevelOperationsTable: options.primary.TopLevelOperationsTable,
|
||||||
promConfigFile: configFile,
|
promConfigFile: configFile,
|
||||||
}
|
}
|
||||||
@ -1698,48 +1700,50 @@ func interfaceArrayToStringArray(array []interface{}) []string {
|
|||||||
return strArray
|
return strArray
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ClickHouseReader) GetServiceMapDependencies(ctx context.Context, queryParams *model.GetServicesParams) (*[]model.ServiceMapDependencyResponseItem, error) {
|
func (r *ClickHouseReader) GetDependencyGraph(ctx context.Context, queryParams *model.GetServicesParams) (*[]model.ServiceMapDependencyResponseItem, error) {
|
||||||
serviceMapDependencyItems := []model.ServiceMapDependencyItem{}
|
|
||||||
|
|
||||||
query := fmt.Sprintf(`SELECT spanID, parentSpanID, serviceName FROM %s.%s WHERE timestamp>='%s' AND timestamp<='%s'`, r.traceDB, r.indexTable, strconv.FormatInt(queryParams.Start.UnixNano(), 10), strconv.FormatInt(queryParams.End.UnixNano(), 10))
|
response := []model.ServiceMapDependencyResponseItem{}
|
||||||
|
|
||||||
err := r.db.Select(ctx, &serviceMapDependencyItems, query)
|
args := []interface{}{}
|
||||||
|
args = append(args,
|
||||||
|
clickhouse.Named("start", uint64(queryParams.Start.Unix())),
|
||||||
|
clickhouse.Named("end", uint64(queryParams.End.Unix())),
|
||||||
|
clickhouse.Named("duration", uint64(queryParams.End.Unix()-queryParams.Start.Unix())),
|
||||||
|
)
|
||||||
|
|
||||||
zap.S().Info(query)
|
query := fmt.Sprintf(`
|
||||||
|
WITH
|
||||||
|
quantilesMergeState(0.5, 0.75, 0.9, 0.95, 0.99)(duration_quantiles_state) AS duration_quantiles_state,
|
||||||
|
finalizeAggregation(duration_quantiles_state) AS result
|
||||||
|
SELECT
|
||||||
|
src as parent,
|
||||||
|
dest as child,
|
||||||
|
result[1] AS p50,
|
||||||
|
result[2] AS p75,
|
||||||
|
result[3] AS p90,
|
||||||
|
result[4] AS p95,
|
||||||
|
result[5] AS p99,
|
||||||
|
sum(total_count) as callCount,
|
||||||
|
sum(total_count)/ @duration AS callRate,
|
||||||
|
sum(error_count)/sum(total_count) as errorRate
|
||||||
|
FROM %s.%s
|
||||||
|
WHERE toUInt64(toDateTime(timestamp)) >= @start AND toUInt64(toDateTime(timestamp)) <= @end
|
||||||
|
GROUP BY
|
||||||
|
src,
|
||||||
|
dest`,
|
||||||
|
r.traceDB, r.dependencyGraphTable,
|
||||||
|
)
|
||||||
|
|
||||||
|
zap.S().Debug(query, args)
|
||||||
|
|
||||||
|
err := r.db.Select(ctx, &response, query, args...)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zap.S().Debug("Error in processing sql query: ", err)
|
zap.S().Error("Error in processing sql query: ", err)
|
||||||
return nil, fmt.Errorf("Error in processing sql query")
|
return nil, fmt.Errorf("Error in processing sql query")
|
||||||
}
|
}
|
||||||
|
|
||||||
serviceMap := make(map[string]*model.ServiceMapDependencyResponseItem)
|
return &response, nil
|
||||||
|
|
||||||
spanId2ServiceNameMap := make(map[string]string)
|
|
||||||
for i := range serviceMapDependencyItems {
|
|
||||||
spanId2ServiceNameMap[serviceMapDependencyItems[i].SpanId] = serviceMapDependencyItems[i].ServiceName
|
|
||||||
}
|
|
||||||
for i := range serviceMapDependencyItems {
|
|
||||||
parent2childServiceName := spanId2ServiceNameMap[serviceMapDependencyItems[i].ParentSpanId] + "-" + spanId2ServiceNameMap[serviceMapDependencyItems[i].SpanId]
|
|
||||||
if _, ok := serviceMap[parent2childServiceName]; !ok {
|
|
||||||
serviceMap[parent2childServiceName] = &model.ServiceMapDependencyResponseItem{
|
|
||||||
Parent: spanId2ServiceNameMap[serviceMapDependencyItems[i].ParentSpanId],
|
|
||||||
Child: spanId2ServiceNameMap[serviceMapDependencyItems[i].SpanId],
|
|
||||||
CallCount: 1,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
serviceMap[parent2childServiceName].CallCount++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
retMe := make([]model.ServiceMapDependencyResponseItem, 0, len(serviceMap))
|
|
||||||
for _, dependency := range serviceMap {
|
|
||||||
if dependency.Parent == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
retMe = append(retMe, *dependency)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &retMe, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ClickHouseReader) GetFilteredSpansAggregates(ctx context.Context, queryParams *model.GetFilteredSpanAggregatesParams) (*model.GetFilteredSpansAggregatesResponse, *model.ApiError) {
|
func (r *ClickHouseReader) GetFilteredSpansAggregates(ctx context.Context, queryParams *model.GetFilteredSpanAggregatesParams) (*model.GetFilteredSpansAggregatesResponse, *model.ApiError) {
|
||||||
@ -1979,7 +1983,7 @@ func (r *ClickHouseReader) SetTTL(ctx context.Context,
|
|||||||
|
|
||||||
switch params.Type {
|
switch params.Type {
|
||||||
case constants.TraceTTL:
|
case constants.TraceTTL:
|
||||||
tableNameArray := []string{signozTraceDBName + "." + signozTraceTableName, signozTraceDBName + "." + signozDurationMVTable, signozTraceDBName + "." + signozSpansTable, signozTraceDBName + "." + signozErrorIndexTable}
|
tableNameArray := []string{signozTraceDBName + "." + signozTraceTableName, signozTraceDBName + "." + signozDurationMVTable, signozTraceDBName + "." + signozSpansTable, signozTraceDBName + "." + signozErrorIndexTable, signozTraceDBName + "." + defaultDependencyGraphTable}
|
||||||
for _, tableName = range tableNameArray {
|
for _, tableName = range tableNameArray {
|
||||||
statusItem, err := r.checkTTLStatusItem(ctx, tableName)
|
statusItem, err := r.checkTTLStatusItem(ctx, tableName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -326,7 +326,7 @@ func (aH *APIHandler) RegisterRoutes(router *mux.Router) {
|
|||||||
router.HandleFunc("/api/v1/service/top_level_operations", ViewAccess(aH.getServicesTopLevelOps)).Methods(http.MethodPost)
|
router.HandleFunc("/api/v1/service/top_level_operations", ViewAccess(aH.getServicesTopLevelOps)).Methods(http.MethodPost)
|
||||||
router.HandleFunc("/api/v1/traces/{traceId}", ViewAccess(aH.searchTraces)).Methods(http.MethodGet)
|
router.HandleFunc("/api/v1/traces/{traceId}", ViewAccess(aH.searchTraces)).Methods(http.MethodGet)
|
||||||
router.HandleFunc("/api/v1/usage", ViewAccess(aH.getUsage)).Methods(http.MethodGet)
|
router.HandleFunc("/api/v1/usage", ViewAccess(aH.getUsage)).Methods(http.MethodGet)
|
||||||
router.HandleFunc("/api/v1/serviceMapDependencies", ViewAccess(aH.serviceMapDependencies)).Methods(http.MethodPost)
|
router.HandleFunc("/api/v1/dependency_graph", ViewAccess(aH.dependencyGraph)).Methods(http.MethodPost)
|
||||||
router.HandleFunc("/api/v1/settings/ttl", AdminAccess(aH.setTTL)).Methods(http.MethodPost)
|
router.HandleFunc("/api/v1/settings/ttl", AdminAccess(aH.setTTL)).Methods(http.MethodPost)
|
||||||
router.HandleFunc("/api/v1/settings/ttl", ViewAccess(aH.getTTL)).Methods(http.MethodGet)
|
router.HandleFunc("/api/v1/settings/ttl", ViewAccess(aH.getTTL)).Methods(http.MethodGet)
|
||||||
|
|
||||||
@ -1185,14 +1185,14 @@ func (aH *APIHandler) getServices(w http.ResponseWriter, r *http.Request) {
|
|||||||
aH.writeJSON(w, r, result)
|
aH.writeJSON(w, r, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (aH *APIHandler) serviceMapDependencies(w http.ResponseWriter, r *http.Request) {
|
func (aH *APIHandler) dependencyGraph(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
query, err := parseGetServicesRequest(r)
|
query, err := parseGetServicesRequest(r)
|
||||||
if aH.handleError(w, err, http.StatusBadRequest) {
|
if aH.handleError(w, err, http.StatusBadRequest) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := (*aH.reader).GetServiceMapDependencies(r.Context(), query)
|
result, err := (*aH.reader).GetDependencyGraph(r.Context(), query)
|
||||||
if aH.handleError(w, err, http.StatusBadRequest) {
|
if aH.handleError(w, err, http.StatusBadRequest) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,8 @@ type Reader interface {
|
|||||||
GetTopOperations(ctx context.Context, query *model.GetTopOperationsParams) (*[]model.TopOperationsItem, *model.ApiError)
|
GetTopOperations(ctx context.Context, query *model.GetTopOperationsParams) (*[]model.TopOperationsItem, *model.ApiError)
|
||||||
GetUsage(ctx context.Context, query *model.GetUsageParams) (*[]model.UsageItem, error)
|
GetUsage(ctx context.Context, query *model.GetUsageParams) (*[]model.UsageItem, error)
|
||||||
GetServicesList(ctx context.Context) (*[]string, error)
|
GetServicesList(ctx context.Context) (*[]string, error)
|
||||||
GetServiceMapDependencies(ctx context.Context, query *model.GetServicesParams) (*[]model.ServiceMapDependencyResponseItem, error)
|
GetDependencyGraph(ctx context.Context, query *model.GetServicesParams) (*[]model.ServiceMapDependencyResponseItem, error)
|
||||||
|
|
||||||
GetTTL(ctx context.Context, ttlParams *model.GetTTLParams) (*model.GetTTLResponseItem, *model.ApiError)
|
GetTTL(ctx context.Context, ttlParams *model.GetTTLParams) (*model.GetTTLResponseItem, *model.ApiError)
|
||||||
|
|
||||||
// GetDisks returns a list of disks configured in the underlying DB. It is supported by
|
// GetDisks returns a list of disks configured in the underlying DB. It is supported by
|
||||||
|
@ -206,12 +206,6 @@ func (item *SearchSpanReponseItem) GetValues() []interface{} {
|
|||||||
return returnArray
|
return returnArray
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServiceMapDependencyItem struct {
|
|
||||||
SpanId string `json:"spanId,omitempty" ch:"spanID"`
|
|
||||||
ParentSpanId string `json:"parentSpanId,omitempty" ch:"parentSpanID"`
|
|
||||||
ServiceName string `json:"serviceName,omitempty" ch:"serviceName"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UsageItem struct {
|
type UsageItem struct {
|
||||||
Time time.Time `json:"time,omitempty" ch:"time"`
|
Time time.Time `json:"time,omitempty" ch:"time"`
|
||||||
Timestamp uint64 `json:"timestamp" ch:"timestamp"`
|
Timestamp uint64 `json:"timestamp" ch:"timestamp"`
|
||||||
@ -233,10 +227,18 @@ type TagFilters struct {
|
|||||||
type TagValues struct {
|
type TagValues struct {
|
||||||
TagValues string `json:"tagValues" ch:"tagValues"`
|
TagValues string `json:"tagValues" ch:"tagValues"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServiceMapDependencyResponseItem struct {
|
type ServiceMapDependencyResponseItem struct {
|
||||||
Parent string `json:"parent,omitempty" ch:"parent"`
|
Parent string `json:"parent" ch:"parent"`
|
||||||
Child string `json:"child,omitempty" ch:"child"`
|
Child string `json:"child" ch:"child"`
|
||||||
CallCount int `json:"callCount,omitempty" ch:"callCount"`
|
CallCount uint64 `json:"callCount" ch:"callCount"`
|
||||||
|
CallRate float64 `json:"callRate" ch:"callRate"`
|
||||||
|
ErrorRate float64 `json:"errorRate" ch:"errorRate"`
|
||||||
|
P99 float64 `json:"p99" ch:"p99"`
|
||||||
|
P95 float64 `json:"p95" ch:"p95"`
|
||||||
|
P90 float64 `json:"p90" ch:"p90"`
|
||||||
|
P75 float64 `json:"p75" ch:"p75"`
|
||||||
|
P50 float64 `json:"p50" ch:"p50"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetFilteredSpansAggregatesResponse struct {
|
type GetFilteredSpansAggregatesResponse struct {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user