mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-06 16:09:41 +00:00
fix: Add more fields to SearchHistoryHitResponse for search history and reuse it (#4702)
- Add `function`, `event`, `_timestamp` and `unit` to `SearchHistoryHitResponse`. - Only include `Search` events for search history - Revert the change made in #4694 i.e. reuse `SearchHIstoryHitResponse` for search history. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes - **New Features** - Enhanced search history functionality with additional metadata fields for more detailed responses. - Improved error handling and logging for search history operations. - Updated data processing logic in the Search History component for accurate representation of timestamps and durations. - **Bug Fixes** - Streamlined data processing and presentation in the Search History component, ensuring accurate display of search history data. - **Documentation** - Updated component and method signatures to reflect changes in data handling and structure. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Sai Nikhil <nikhil@openobserve.ai>
This commit is contained in:
@@ -446,6 +446,14 @@ pub struct SearchHistoryHitResponse {
|
||||
pub response_time: f64,
|
||||
pub cached_ratio: i64,
|
||||
pub trace_id: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub function: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub _timestamp: Option<i64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub unit: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub event: Option<String>,
|
||||
}
|
||||
|
||||
impl TryFrom<json::Value> for SearchHistoryHitResponse {
|
||||
@@ -502,6 +510,19 @@ impl TryFrom<json::Value> for SearchHistoryHitResponse {
|
||||
.and_then(|v| v.as_str())
|
||||
.ok_or("trace_id missing".to_string())?
|
||||
.to_string(),
|
||||
function: value
|
||||
.get("function")
|
||||
.and_then(|v| v.as_str())
|
||||
.map(|v| v.to_string()),
|
||||
_timestamp: value.get("_timestamp").and_then(|v| v.as_i64()),
|
||||
unit: value
|
||||
.get("unit")
|
||||
.and_then(|v| v.as_str())
|
||||
.map(|v| v.to_string()),
|
||||
event: value
|
||||
.get("event")
|
||||
.and_then(|v| v.as_str())
|
||||
.map(|v| v.to_string()),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -993,7 +1014,7 @@ mod search_history_utils {
|
||||
|
||||
// Method to build the SQL query
|
||||
pub fn build(self, search_stream_name: &str) -> String {
|
||||
let mut query = format!("SELECT * FROM {} WHERE 1=1", search_stream_name);
|
||||
let mut query = format!("SELECT * FROM {} WHERE event='Search'", search_stream_name);
|
||||
|
||||
if let Some(org_id) = self.org_id {
|
||||
if !org_id.is_empty() {
|
||||
|
||||
@@ -21,7 +21,7 @@ use chrono::{Duration, Utc};
|
||||
use config::{
|
||||
get_config,
|
||||
meta::{
|
||||
search::SearchEventType,
|
||||
search::{SearchEventType, SearchHistoryHitResponse},
|
||||
sql::resolve_stream_names,
|
||||
stream::StreamType,
|
||||
usage::{RequestStats, UsageType, USAGE_STREAM},
|
||||
@@ -1435,7 +1435,7 @@ pub async fn search_partition(
|
||||
"stream_type": "logs",
|
||||
"took": 0.056222333,
|
||||
"trace_id": "7f7898fd19424c47ba830a6fa9b25e1f",
|
||||
"user_email": "root@example.com"
|
||||
"function": ".",
|
||||
},
|
||||
],
|
||||
"total": 3,
|
||||
@@ -1558,6 +1558,24 @@ pub async fn search_history(
|
||||
}
|
||||
};
|
||||
|
||||
search_res.hits = search_res
|
||||
.hits
|
||||
.into_iter()
|
||||
.filter_map(|hit| match SearchHistoryHitResponse::try_from(hit) {
|
||||
Ok(response) => match serde_json::to_value(response) {
|
||||
Ok(json_value) => Some(json_value),
|
||||
Err(e) => {
|
||||
log::error!("[trace_id {}] Serialization error: {:?}", trace_id, e);
|
||||
None
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
log::error!("[trace_id {}] Deserialization error: {:?}", trace_id, e);
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
search_res.trace_id = trace_id.clone();
|
||||
|
||||
// report http metrics
|
||||
|
||||
@@ -147,7 +147,7 @@
|
||||
</div>
|
||||
<div v-if="props.row?.function" class="text-left q-mb-sm tw-px-2 expanded-content">
|
||||
<div class="tw-flex tw-items-center q-py-sm ">
|
||||
<strong >Function Defination : <span> <q-btn
|
||||
<strong >Function Definition : <span> <q-btn
|
||||
@click.stop="copyToClipboard(props.row.function, 'Function Defination')"
|
||||
size="xs"
|
||||
dense
|
||||
@@ -383,22 +383,22 @@
|
||||
columnsToBeRendered.value = generateColumns(filteredHits);
|
||||
filteredHits.forEach((hit:any)=>{
|
||||
|
||||
const {formatted, raw} = calculateDuration(hit.min_ts, hit.max_ts);
|
||||
const {formatted, raw} = calculateDuration(hit.start_time, hit.end_time);
|
||||
hit.duration = formatted;
|
||||
hit.rawDuration = raw;
|
||||
hit.toBeStoredStartTime = hit.min_ts;
|
||||
hit.toBeStoredEndTime = hit.max_ts;
|
||||
hit.start_time = timestampToTimezoneDate(hit.min_ts / 1000, store.state.timezone, "yyyy-MM-dd HH:mm:ss.SSS");
|
||||
hit.end_time = timestampToTimezoneDate(hit.max_ts / 1000, store.state.timezone, "yyyy-MM-dd HH:mm:ss.SSS");
|
||||
hit.rawTook = hit.response_time;
|
||||
hit.took = formatTime(hit.response_time);
|
||||
hit.scan_records = hit.num_records;
|
||||
hit.rawScanRecords = hit.num_records;
|
||||
hit.scan_size = hit.size + hit.unit;
|
||||
hit.rawScanSize = hit.size;
|
||||
hit.toBeStoredStartTime = hit.start_time;
|
||||
hit.toBeStoredEndTime = hit.end_time;
|
||||
hit.start_time = timestampToTimezoneDate(hit.start_time / 1000, store.state.timezone, "yyyy-MM-dd HH:mm:ss.SSS");
|
||||
hit.end_time = timestampToTimezoneDate(hit.end_time / 1000, store.state.timezone, "yyyy-MM-dd HH:mm:ss.SSS");
|
||||
hit.rawTook = hit.took;
|
||||
hit.took = formatTime(hit.took);
|
||||
hit.rawScanRecords = hit.scan_records;
|
||||
hit.scan_records = hit.scan_records;
|
||||
hit.rawScanSize = hit.scan_size;
|
||||
hit.scan_size = hit.scan_size + hit.unit;
|
||||
hit.cached_ratio = hit.cached_ratio;
|
||||
hit.rawCachedRatio = hit.cached_ratio;
|
||||
hit.sql = hit.request_body;
|
||||
hit.sql = hit.sql;
|
||||
hit.function = hit.function;
|
||||
hit.rawExecutedTime = hit._timestamp;
|
||||
hit.executed_time = timestampToTimezoneDate(hit._timestamp / 1000, store.state.timezone, "yyyy-MM-dd HH:mm:ss.SSS");
|
||||
@@ -420,7 +420,7 @@
|
||||
|
||||
|
||||
};
|
||||
|
||||
//this method needs to revamped / can be made shorter
|
||||
const sortMethod = (rows, sortBy, descending) => {
|
||||
const data = [...rows];
|
||||
if(sortBy === 'duration'){
|
||||
@@ -450,13 +450,6 @@
|
||||
// console.log(data.sort((a, b) => a.rawScanRecords - b.rawScanRecords), "data")
|
||||
return data.sort((a, b) => a.rawScanSize - b.rawScanSize);
|
||||
}
|
||||
if(sortBy === "scan_size"){
|
||||
if (descending) {
|
||||
return data.sort((a, b) => b.rawScanSize - a.rawScanSize);
|
||||
}
|
||||
// console.log(data.sort((a, b) => a.rawScanRecords - b.rawScanRecords), "data")
|
||||
return data.sort((a, b) => a.rawScanSize - b.rawScanSize);
|
||||
}
|
||||
if(sortBy === "cached_ratio"){
|
||||
if (descending) {
|
||||
return data.sort((a, b) => b.rawCachedRatio - a.rawCachedRatio);
|
||||
@@ -681,7 +674,7 @@
|
||||
<style lang="scss" scoped >
|
||||
.expanded-content {
|
||||
padding: 0 3rem;
|
||||
min-width: 100vh;
|
||||
min-width: 100vw;
|
||||
max-height: 100vh; /* Set a fixed height for the container */
|
||||
overflow: hidden; /* Hide overflow by default */
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user