import React, { useState, useEffect } from "react"; import GenericVisualizations from "../Metrics/GenericVisualization"; import { Select, Card, Space, Form } from "antd"; import { connect } from "react-redux"; import { StoreState } from "../../store/reducers"; import { GlobalTime, TraceFilters } from "../../store/actions"; import { useRoute } from "../RouteProvider"; import { getFilteredTraceMetrics } from "../../store/actions/MetricsActions"; import { customMetricsItem } from "../../store/actions/MetricsActions"; const { Option } = Select; const entity = [ { title: "Calls", key: "calls", dataindex: "calls", }, { title: "Duration", key: "duration", dataindex: "duration", }, { title: "Error", key: "error", dataindex: "error", }, { title: "Status Code", key: "status_code", dataindex: "status_code", }, ]; const aggregation_options = [ { linked_entity: "calls", default_selected: { title: "Count", dataindex: "count" }, options_available: [ { title: "Count", dataindex: "count" }, { title: "Rate (per sec)", dataindex: "rate_per_sec" }, ], }, { linked_entity: "duration", default_selected: { title: "p99", dataindex: "p99" }, // options_available: [ {title:'Avg', dataindex:'avg'}, {title:'Max', dataindex:'max'},{title:'Min', dataindex:'min'}, {title:'p50', dataindex:'p50'},{title:'p95', dataindex:'p95'}, {title:'p95', dataindex:'p95'}] options_available: [ { title: "p50", dataindex: "p50" }, { title: "p95", dataindex: "p95" }, { title: "p99", dataindex: "p99" }, ], }, { linked_entity: "error", default_selected: { title: "Count", dataindex: "count" }, options_available: [ { title: "Count", dataindex: "count" }, { title: "Rate (per sec)", dataindex: "rate_per_sec" }, ], }, { linked_entity: "status_code", default_selected: { title: "Count", dataindex: "count" }, options_available: [{ title: "Count", dataindex: "count" }], }, ]; interface TraceCustomVisualizationsProps { filteredTraceMetrics: customMetricsItem[]; globalTime: GlobalTime; getFilteredTraceMetrics: Function; traceFilters: TraceFilters; } const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => { const [selectedEntity, setSelectedEntity] = useState("calls"); const [selectedAggOption, setSelectedAggOption] = useState("count"); const { state } = useRoute(); const [form] = Form.useForm(); const selectedStep = "60"; // Step should be multiples of 60, 60 -> 1 min useEffect(() => { let request_string = "service=" + props.traceFilters.service + "&operation=" + props.traceFilters.operation + "&maxDuration=" + props.traceFilters.latency?.max + "&minDuration=" + props.traceFilters.latency?.min; if (props.traceFilters.tags) request_string = request_string + "&tags=" + encodeURIComponent(JSON.stringify(props.traceFilters.tags)); if (selectedEntity) request_string = request_string + "&dimension=" + selectedEntity.toLowerCase(); if (selectedAggOption) request_string = request_string + "&aggregation_option=" + selectedAggOption.toLowerCase(); if (selectedStep) request_string = request_string + "&step=" + selectedStep; const plusMinus15 = { minTime: props.globalTime.minTime - 15 * 60 * 1000000000, maxTime: props.globalTime.maxTime + 15 * 60 * 1000000000, }; /* Call the apis only when the route is loaded. Check this issue: https://github.com/SigNoz/signoz/issues/110 */ if (state.TRACES.isLoaded) { props.getFilteredTraceMetrics(request_string, plusMinus15); } }, [selectedEntity, selectedAggOption, props.traceFilters, props.globalTime]); //Custom metrics API called if time, tracefilters, selected entity or agg option changes // PNOTE - Can also use 'coordinate' option in antd Select for implementing this - https://ant.design/components/select/ const handleFormValuesChange = (changedValues: any) => { const formFieldName = Object.keys(changedValues)[0]; if (formFieldName === "entity") { const temp_entity = aggregation_options.filter( (item) => item.linked_entity === changedValues[formFieldName], )[0]; form.setFieldsValue({ agg_options: temp_entity.default_selected.title, // PNOTE - TO DO Check if this has the same behaviour as selecting an option? }); let temp = form.getFieldsValue(["agg_options", "entity"]); setSelectedEntity(temp.entity); setSelectedAggOption(temp.agg_options); //form.setFieldsValue({ agg_options: aggregation_options.filter( item => item.linked_entity === selectedEntity )[0] }); //reset product selection // PNOTE - https://stackoverflow.com/questions/64377293/update-select-option-list-based-on-other-select-field-selection-ant-design } if (formFieldName === "agg_options") { setSelectedAggOption(changedValues[formFieldName]); } }; return (
Custom Visualizations
{/* Need heading for each option */}
{/* This component should take bar or line as an input */}
); }; const mapStateToProps = ( state: StoreState, ): { filteredTraceMetrics: customMetricsItem[]; globalTime: GlobalTime; traceFilters: TraceFilters; } => { return { filteredTraceMetrics: state.metricsData.customMetricsItem, globalTime: state.globalTime, traceFilters: state.traceFilters, }; }; export const TraceCustomVisualizations = connect(mapStateToProps, { getFilteredTraceMetrics: getFilteredTraceMetrics, })(_TraceCustomVisualizations);