Skip to content

Commit d547ef5

Browse files
add duplicate and empty check
1 parent 48b90ff commit d547ef5

File tree

2 files changed

+42
-16
lines changed

2 files changed

+42
-16
lines changed

src/handlers/http/modal/utils/ingest_utils.rs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@
1616
*
1717
*/
1818

19-
use std::collections::HashMap;
20-
2119
use actix_web::HttpRequest;
2220
use chrono::Utc;
2321
use http::header::USER_AGENT;
2422
use opentelemetry_proto::tonic::{
2523
logs::v1::LogsData, metrics::v1::MetricsData, trace::v1::TracesData,
2624
};
2725
use serde_json::Value;
26+
use std::collections::HashMap;
27+
use tracing::warn;
2828

2929
use crate::{
3030
event::{
@@ -164,7 +164,14 @@ pub fn get_custom_fields_from_header(req: HttpRequest) -> HashMap<String, String
164164
if header_name.starts_with("x-p-") && !IGNORE_HEADERS.contains(&header_name) {
165165
if let Ok(value) = header_value.to_str() {
166166
let key = header_name.trim_start_matches("x-p-");
167-
p_custom_fields.insert(key.to_string(), value.to_string());
167+
if !key.is_empty() {
168+
p_custom_fields.insert(key.to_string(), value.to_string());
169+
} else {
170+
warn!(
171+
"Ignoring header with empty key after prefix: {}",
172+
header_name
173+
);
174+
}
168175
}
169176
}
170177

@@ -221,4 +228,17 @@ mod tests {
221228
assert_eq!(custom_fields.get(USER_AGENT_KEY).unwrap(), "TestUserAgent");
222229
assert_eq!(custom_fields.get(FORMAT_KEY).unwrap(), "otel-logs");
223230
}
231+
232+
#[test]
233+
fn test_get_custom_fields_empty_header_after_prefix() {
234+
let req = TestRequest::default()
235+
.insert_header(("x-p-", "empty"))
236+
.to_http_request();
237+
238+
let custom_fields = get_custom_fields_from_header(req);
239+
240+
assert_eq!(custom_fields.len(), 2);
241+
assert_eq!(custom_fields.get(USER_AGENT_KEY).unwrap(), "");
242+
assert_eq!(custom_fields.get(SOURCE_IP_KEY).unwrap(), "");
243+
}
224244
}

src/utils/arrow/mod.rs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@
4040
//! }
4141
//! ```
4242
43-
use std::{collections::HashMap, sync::Arc};
43+
use std::{
44+
collections::{HashMap, HashSet},
45+
sync::Arc,
46+
};
4447

4548
use arrow_array::{
4649
Array, ArrayRef, RecordBatch, StringArray, TimestampMillisecondArray, UInt64Array,
@@ -162,6 +165,8 @@ pub fn add_parseable_fields(
162165
.iter()
163166
.map(|f| f.as_ref().clone())
164167
.collect_vec();
168+
let mut field_names: HashSet<String> = fields.iter().map(|f| f.name().to_string()).collect();
169+
165170
fields.insert(
166171
0,
167172
Field::new(
@@ -170,23 +175,24 @@ pub fn add_parseable_fields(
170175
true,
171176
),
172177
);
173-
fields.extend(
174-
sorted_keys
175-
.iter()
176-
.map(|k| Field::new(*k, DataType::Utf8, true)),
177-
);
178-
179178
let mut columns = rb.columns().iter().map(Arc::clone).collect_vec();
180179
columns.insert(
181180
0,
182181
Arc::new(get_timestamp_array(p_timestamp, row_count)) as ArrayRef,
183182
);
184-
columns.extend(sorted_keys.iter().map(|k| {
185-
let value = p_custom_fields.get(*k).unwrap();
186-
Arc::new(StringArray::from_iter_values(
187-
std::iter::repeat(value).take(row_count),
188-
)) as ArrayRef
189-
}));
183+
184+
//ignore the duplicate fields, no need to add them again
185+
for key in sorted_keys {
186+
if !field_names.contains(key) {
187+
fields.push(Field::new(key, DataType::Utf8, true));
188+
field_names.insert(key.to_string());
189+
190+
let value = p_custom_fields.get(key).unwrap();
191+
columns.push(Arc::new(StringArray::from_iter_values(
192+
std::iter::repeat(value).take(row_count),
193+
)) as ArrayRef);
194+
}
195+
}
190196

191197
// Create the new schema and batch
192198
let new_schema = Arc::new(Schema::new(fields));

0 commit comments

Comments
 (0)