Skip to content

Commit 0fa8a6c

Browse files
emmaling27Convex, Inc.
authored and
Convex, Inc.
committed
Add ComponentPath to UdfIdentifier (#27943)
This PR adds `ComponentPath` to `UdfIdentifier`, which we need for namespacing logs and usage. I updated the `/app_metrics` API endpoints to take in component path. I'll follow up with adding that to the dashboard app_metrics calls after backend is pushed with this. GitOrigin-RevId: f87f9667711b865a387a83afcbdcc1dd62d779ef
1 parent 172bebb commit 0fa8a6c

File tree

6 files changed

+81
-26
lines changed

6 files changed

+81
-26
lines changed

crates/application/src/function_log.rs

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ use std::{
1313
};
1414

1515
use common::{
16-
components::CanonicalizedComponentFunctionPath,
16+
components::{
17+
CanonicalizedComponentFunctionPath,
18+
ComponentFunctionPath,
19+
ComponentPath,
20+
},
1721
errors::{
1822
report_error,
1923
JsError,
@@ -191,7 +195,14 @@ impl FunctionExecution {
191195

192196
fn identifier(&self) -> UdfIdentifier {
193197
match &self.params {
194-
UdfParams::Function { identifier, .. } => UdfIdentifier::Function(identifier.clone()),
198+
UdfParams::Function { identifier, .. } => {
199+
let component = ComponentPath::TODO();
200+
let path = ComponentFunctionPath {
201+
component,
202+
udf_path: identifier.clone().strip(),
203+
};
204+
UdfIdentifier::Function(path.canonicalize())
205+
},
195206
UdfParams::Http { identifier, .. } => UdfIdentifier::Http(identifier.clone()),
196207
}
197208
}
@@ -622,8 +633,13 @@ impl<RT: Runtime> FunctionExecutionLog<RT> {
622633
TrackUsage::Track(usage_tracker) => {
623634
let usage_stats = usage_tracker.gather_user_stats();
624635
let aggregated = usage_stats.aggregate();
636+
let component = ComponentPath::TODO();
637+
let path = ComponentFunctionPath {
638+
component,
639+
udf_path: udf_path.clone().strip(),
640+
};
625641
self.usage_tracking.track_call(
626-
UdfIdentifier::Function(udf_path.clone()),
642+
UdfIdentifier::Function(path.canonicalize()),
627643
context.execution_id.clone(),
628644
if was_cached {
629645
CallType::CachedQuery
@@ -759,8 +775,13 @@ impl<RT: Runtime> FunctionExecutionLog<RT> {
759775
TrackUsage::Track(usage_tracker) => {
760776
let usage_stats = usage_tracker.gather_user_stats();
761777
let aggregated = usage_stats.aggregate();
778+
let component = ComponentPath::TODO();
779+
let path = ComponentFunctionPath {
780+
component,
781+
udf_path: udf_path.clone().strip(),
782+
};
762783
self.usage_tracking.track_call(
763-
UdfIdentifier::Function(udf_path.clone()),
784+
UdfIdentifier::Function(path.canonicalize()),
764785
context.execution_id.clone(),
765786
CallType::Mutation,
766787
usage_stats,
@@ -854,8 +875,13 @@ impl<RT: Runtime> FunctionExecutionLog<RT> {
854875
TrackUsage::Track(usage_tracker) => {
855876
let usage_stats = usage_tracker.gather_user_stats();
856877
let aggregated = usage_stats.aggregate();
878+
let component = ComponentPath::TODO();
879+
let path = ComponentFunctionPath {
880+
component,
881+
udf_path: udf_path.clone().strip(),
882+
};
857883
self.usage_tracking.track_call(
858-
UdfIdentifier::Function(udf_path.clone()),
884+
UdfIdentifier::Function(path.canonicalize()),
859885
completion.context.execution_id.clone(),
860886
CallType::Action {
861887
env: completion.environment,

crates/common/src/components/component_path.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@ impl ComponentPath {
113113
format!(" in '{}'", String::from(self.clone()))
114114
}
115115
}
116+
117+
pub fn deserialize(path: Option<&str>) -> anyhow::Result<Self> {
118+
match path {
119+
Some(p) => p.parse(),
120+
None => Ok(ComponentPath::root()),
121+
}
122+
}
116123
}
117124

118125
impl Deref for ComponentPath {

crates/common/src/types/functions.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,16 @@ use serde::{
1313
Deserialize,
1414
Serialize,
1515
};
16-
use sync_types::CanonicalizedUdfPath;
1716
use value::{
1817
heap_size::HeapSize,
1918
id_v6::DeveloperDocumentId,
2019
};
2120

2221
use super::HttpActionRoute;
23-
use crate::version::ClientVersion;
22+
use crate::{
23+
components::CanonicalizedComponentFunctionPath,
24+
version::ClientVersion,
25+
};
2426

2527
#[derive(Serialize, Copy, Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
2628
#[serde(rename_all = "camelCase")]
@@ -104,15 +106,15 @@ impl From<UdfTypeProto> for UdfType {
104106
/// A unique identifier for a UDF
105107
#[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
106108
pub enum UdfIdentifier {
107-
Function(CanonicalizedUdfPath),
109+
Function(CanonicalizedComponentFunctionPath),
108110
Http(HttpActionRoute),
109111
Cli(String),
110112
}
111113

112114
impl fmt::Display for UdfIdentifier {
113115
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
114116
match self {
115-
UdfIdentifier::Function(path) => write!(f, "{}", path),
117+
UdfIdentifier::Function(path) => write!(f, "{}", path.debug_str()),
116118
UdfIdentifier::Http(route) => write!(f, "{}", route.path),
117119
UdfIdentifier::Cli(command) => write!(f, "_cli/{command}"),
118120
}

crates/database/src/tests/usage_tracking.rs

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ use std::time::Duration;
33
use common::{
44
assert_obj,
55
bootstrap_model::index::IndexMetadata,
6+
components::{
7+
ComponentFunctionPath,
8+
ComponentPath,
9+
},
610
execution_context::ExecutionId,
711
maybe_val,
812
query::{
@@ -22,6 +26,7 @@ use keybroker::Identity;
2226
use maplit::btreeset;
2327
use pretty_assertions::assert_eq;
2428
use runtime::testing::TestRuntime;
29+
use sync_types::CanonicalizedUdfPath;
2530
use usage_tracking::{
2631
CallType,
2732
FunctionUsageTracker,
@@ -41,6 +46,16 @@ use crate::{
4146
UserFacingModel,
4247
};
4348

49+
fn test_udf_identifier() -> UdfIdentifier {
50+
let udf_path: CanonicalizedUdfPath = "test.js:default".parse().unwrap();
51+
let component = ComponentPath::root();
52+
let path = ComponentFunctionPath {
53+
component,
54+
udf_path: udf_path.strip(),
55+
};
56+
UdfIdentifier::Function(path.canonicalize())
57+
}
58+
4459
#[convex_macro::test_runtime]
4560
async fn vector_insert_with_no_index_does_not_count_usage(rt: TestRuntime) -> anyhow::Result<()> {
4661
let fixtures = VectorFixtures::new(rt).await?;
@@ -55,7 +70,7 @@ async fn vector_insert_with_no_index_does_not_count_usage(rt: TestRuntime) -> an
5570
add_document_vec_array(&mut tx, &table_name, [3f64, 4f64]).await?;
5671
fixtures.db.commit(tx).await?;
5772
fixtures.db.usage_counter().track_call(
58-
UdfIdentifier::Function("test.js:default".parse()?),
73+
test_udf_identifier(),
5974
ExecutionId::new(),
6075
CallType::Action {
6176
env: ModuleEnvironment::Isolate,
@@ -84,7 +99,7 @@ async fn vector_insert_counts_usage_for_backfilling_indexes(rt: TestRuntime) ->
8499
add_document_vec_array(&mut tx, index_name.table(), [3f64, 4f64]).await?;
85100
fixtures.db.commit(tx).await?;
86101
fixtures.db.usage_counter().track_call(
87-
UdfIdentifier::Function("test.js:default".parse()?),
102+
test_udf_identifier(),
88103
ExecutionId::new(),
89104
CallType::Mutation,
90105
tx_usage.gather_user_stats(),
@@ -117,7 +132,7 @@ async fn vector_insert_counts_usage_for_enabled_indexes(rt: TestRuntime) -> anyh
117132
add_document_vec_array(&mut tx, index_name.table(), [3f64, 4f64]).await?;
118133
fixtures.db.commit(tx).await?;
119134
fixtures.db.usage_counter().track_call(
120-
UdfIdentifier::Function("test.js:default".parse()?),
135+
test_udf_identifier(),
121136
ExecutionId::new(),
122137
CallType::Action {
123138
env: ModuleEnvironment::Isolate,
@@ -150,7 +165,7 @@ async fn vectors_in_segment_count_as_usage(rt: TestRuntime) -> anyhow::Result<()
150165
add_document_vec_array(&mut tx, index_name.table(), [3f64, 4f64]).await?;
151166
fixtures.db.commit(tx).await?;
152167
fixtures.db.usage_counter().track_call(
153-
UdfIdentifier::Function("test.js:default".parse()?),
168+
test_udf_identifier(),
154169
ExecutionId::new(),
155170
CallType::Action {
156171
env: ModuleEnvironment::Isolate,
@@ -199,7 +214,7 @@ async fn vector_query_counts_bandwidth(rt: TestRuntime) -> anyhow::Result<()> {
199214
tx_usage.add(usage_stats);
200215

201216
fixtures.db.usage_counter().track_call(
202-
UdfIdentifier::Function("test.js:default".parse()?),
217+
test_udf_identifier(),
203218
ExecutionId::new(),
204219
CallType::Action {
205220
env: ModuleEnvironment::Isolate,
@@ -241,7 +256,7 @@ async fn test_usage_tracking_basic_insert_and_get(rt: TestRuntime) -> anyhow::Re
241256
.await?;
242257
db.commit(tx).await?;
243258
db.usage_counter().track_call(
244-
UdfIdentifier::Function("test.js:default".parse()?),
259+
test_udf_identifier(),
245260
ExecutionId::new(),
246261
CallType::Mutation,
247262
tx_usage.gather_user_stats(),
@@ -266,7 +281,7 @@ async fn test_usage_tracking_basic_insert_and_get(rt: TestRuntime) -> anyhow::Re
266281
.await?;
267282
db.commit(tx).await?;
268283
db.usage_counter().track_call(
269-
UdfIdentifier::Function("test.js:default".parse()?),
284+
test_udf_identifier(),
270285
ExecutionId::new(),
271286
CallType::Mutation,
272287
tx_usage.gather_user_stats(),
@@ -308,7 +323,7 @@ async fn test_usage_tracking_insert_with_index(rt: TestRuntime) -> anyhow::Resul
308323
.unwrap_or_else(|e| panic!("Failed to add index for {} {:?}", "by_key", e));
309324
db.commit(tx).await?;
310325
db.usage_counter().track_call(
311-
UdfIdentifier::Function("test.js:default".parse()?),
326+
test_udf_identifier(),
312327
ExecutionId::new(),
313328
CallType::Mutation,
314329
tx_usage.gather_user_stats(),
@@ -332,7 +347,7 @@ async fn test_usage_tracking_insert_with_index(rt: TestRuntime) -> anyhow::Resul
332347
.await?;
333348
db.commit(tx).await?;
334349
db.usage_counter().track_call(
335-
UdfIdentifier::Function("test.js:default".parse()?),
350+
test_udf_identifier(),
336351
ExecutionId::new(),
337352
CallType::Mutation,
338353
tx_usage.gather_user_stats(),
@@ -359,7 +374,7 @@ async fn test_usage_tracking_insert_with_index(rt: TestRuntime) -> anyhow::Resul
359374
while query_stream.next(&mut tx, None).await?.is_some() {}
360375
db.commit(tx).await?;
361376
db.usage_counter().track_call(
362-
UdfIdentifier::Function("test.js:default".parse()?),
377+
test_udf_identifier(),
363378
ExecutionId::new(),
364379
CallType::Mutation,
365380
tx_usage.gather_user_stats(),
@@ -386,7 +401,7 @@ async fn http_action_counts_compute(rt: TestRuntime) -> anyhow::Result<()> {
386401

387402
let tx_usage = FunctionUsageTracker::new();
388403
db.usage_counter().track_call(
389-
UdfIdentifier::Function("test.js:default".parse()?),
404+
test_udf_identifier(),
390405
ExecutionId::new(),
391406
CallType::HttpAction {
392407
duration: Duration::from_secs(5),

crates/local_backend/src/node_action_callbacks.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ use serde_json::{
6262
};
6363
use sync_types::{
6464
AuthenticationToken,
65+
CanonicalizedUdfPath,
6566
UdfPath,
6667
};
6768
use usage_tracking::FunctionUsageTracker;
@@ -321,12 +322,16 @@ pub async fn vector_search(
321322
if let Some(action_name) = action_name {
322323
let usage = FunctionUsageTracker::new();
323324
usage.add(usage_stats);
325+
let component = ComponentPath::TODO();
326+
let udf_path: CanonicalizedUdfPath = action_name
327+
.parse()
328+
.context(format!("Unexpected udf path format, got {action_name}"))?;
329+
let path = ComponentFunctionPath {
330+
component,
331+
udf_path: udf_path.clone().strip(),
332+
};
324333
st.application.usage_counter().track_function_usage(
325-
UdfIdentifier::Function(
326-
action_name
327-
.parse()
328-
.context(format!("Unexpected udf path format, got {action_name}"))?,
329-
),
334+
UdfIdentifier::Function(path.canonicalize()),
330335
// TODO(CX-6045) - have the action send the ExecutionId as a request header
331336
context.execution_id,
332337
usage.gather_user_stats(),

crates/usage_tracking/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ impl UsageCounter {
114114
// Because system udfs might cause usage before any data is added by the user,
115115
// we do not count their calls. We do count their bandwidth.
116116
let (should_track_calls, udf_id_type) = match &udf_path {
117-
UdfIdentifier::Function(path) => (!path.is_system(), "function"),
117+
UdfIdentifier::Function(path) => (!path.udf_path.is_system(), "function"),
118118
UdfIdentifier::Http(_) => (true, "http"),
119119
UdfIdentifier::Cli(_) => (false, "cli"),
120120
};

0 commit comments

Comments
 (0)