Skip to content

Commit

Permalink
feat(turbopack): define module feature telemtry type
Browse files Browse the repository at this point in the history
  • Loading branch information
kwonoj committed Jul 10, 2023
1 parent d175aea commit 29be469
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 9 deletions.
1 change: 1 addition & 0 deletions packages/next-swc/crates/next-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ mod transform_options;
pub mod url_node;
mod util;
mod web_entry_source;
mod next_telemetry;

pub use app_source::create_app_source;
pub use page_loader::create_page_loader_entry_asset;
Expand Down
11 changes: 9 additions & 2 deletions packages/next-swc/crates/next-core/src/next_client/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ use crate::{
get_next_client_resolved_map, mdx_import_source_file,
},
next_shared::{
resolve::UnsupportedModulesResolvePluginVc,
resolve::{ModuleFeatureReportResolvePluginVc, UnsupportedModulesResolvePluginVc},
transforms::{
emotion::get_emotion_transform_plugin, get_relay_transform_plugin,
styled_components::get_styled_components_transform_plugin,
Expand Down Expand Up @@ -150,7 +150,14 @@ pub async fn get_client_resolve_options_context(
resolved_map: Some(next_client_resolved_map),
browser: true,
module: true,
plugins: vec![UnsupportedModulesResolvePluginVc::new(project_path).into()],
plugins: vec![
ModuleFeatureReportResolvePluginVc::new(
project_path,
StringVc::cell("next_client".to_string()),
)
.into(),
UnsupportedModulesResolvePluginVc::new(project_path).into(),
],
..Default::default()
};
Ok(ResolveOptionsContext {
Expand Down
17 changes: 13 additions & 4 deletions packages/next-swc/crates/next-core/src/next_edge/context.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use anyhow::Result;
use turbo_tasks::Value;
use turbo_tasks::{primitives::StringVc, Value};
use turbopack_binding::{
turbo::tasks_fs::FileSystemPathVc,
turbopack::{
Expand All @@ -20,9 +20,11 @@ use turbopack_binding::{
};

use crate::{
next_config::NextConfigVc, next_import_map::get_next_edge_import_map,
next_config::NextConfigVc,
next_import_map::get_next_edge_import_map,
next_server::context::ServerContextType,
next_shared::resolve::UnsupportedModulesResolvePluginVc, util::foreign_code_context_condition,
next_shared::resolve::{ModuleFeatureReportResolvePluginVc, UnsupportedModulesResolvePluginVc},
util::foreign_code_context_condition,
};

fn defines() -> CompileTimeDefines {
Expand Down Expand Up @@ -93,7 +95,14 @@ pub async fn get_edge_resolve_options_context(
import_map: Some(next_edge_import_map),
module: true,
browser: true,
plugins: vec![UnsupportedModulesResolvePluginVc::new(project_path).into()],
plugins: vec![
ModuleFeatureReportResolvePluginVc::new(
project_path,
StringVc::cell("next_edge".to_string()),
)
.into(),
UnsupportedModulesResolvePluginVc::new(project_path).into(),
],
..Default::default()
};

Expand Down
15 changes: 13 additions & 2 deletions packages/next-swc/crates/next-core/src/next_server/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ use crate::{
next_import_map::{get_next_server_import_map, mdx_import_source_file},
next_server::resolve::ExternalPredicate,
next_shared::{
resolve::UnsupportedModulesResolvePluginVc,
resolve::{ModuleFeatureReportResolvePluginVc, UnsupportedModulesResolvePluginVc},
transforms::{
emotion::get_emotion_transform_plugin, get_relay_transform_plugin,
styled_components::get_styled_components_transform_plugin,
Expand Down Expand Up @@ -81,6 +81,10 @@ pub async fn get_server_resolve_options_context(
get_next_server_import_map(project_path, ty, next_config, execution_context);
let foreign_code_context_condition = foreign_code_context_condition(next_config).await?;
let root_dir = project_path.root().resolve().await?;
let module_feature_report_resolve_plugin = ModuleFeatureReportResolvePluginVc::new(
project_path,
StringVc::cell("next_server".to_string()),
);
let unsupported_modules_resolve_plugin = UnsupportedModulesResolvePluginVc::new(project_path);
let server_component_externals_plugin = ExternalCjsModulesResolvePluginVc::new(
project_path,
Expand All @@ -103,6 +107,7 @@ pub async fn get_server_resolve_options_context(
import_map: Some(next_server_import_map),
plugins: vec![
external_cjs_modules_plugin.into(),
module_feature_report_resolve_plugin.into(),
unsupported_modules_resolve_plugin.into(),
],
..Default::default()
Expand Down Expand Up @@ -131,6 +136,7 @@ pub async fn get_server_resolve_options_context(
import_map: Some(next_server_import_map),
plugins: vec![
server_component_externals_plugin.into(),
module_feature_report_resolve_plugin.into(),
unsupported_modules_resolve_plugin.into(),
],
..Default::default()
Expand Down Expand Up @@ -160,6 +166,7 @@ pub async fn get_server_resolve_options_context(
import_map: Some(next_server_import_map),
plugins: vec![
server_component_externals_plugin.into(),
module_feature_report_resolve_plugin.into(),
unsupported_modules_resolve_plugin.into(),
],
..Default::default()
Expand All @@ -182,6 +189,7 @@ pub async fn get_server_resolve_options_context(
import_map: Some(next_server_import_map),
plugins: vec![
server_component_externals_plugin.into(),
module_feature_report_resolve_plugin.into(),
unsupported_modules_resolve_plugin.into(),
],
..Default::default()
Expand All @@ -202,7 +210,10 @@ pub async fn get_server_resolve_options_context(
enable_node_externals: true,
module: true,
custom_conditions: vec![mode.node_env().to_string()],
plugins: vec![unsupported_modules_resolve_plugin.into()],
plugins: vec![
module_feature_report_resolve_plugin.into(),
unsupported_modules_resolve_plugin.into(),
],
..Default::default()
};
ResolveOptionsContext {
Expand Down
81 changes: 80 additions & 1 deletion packages/next-swc/crates/next-core/src/next_shared/resolve.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use std::collections::HashSet;
use std::collections::{HashMap, HashSet};

use anyhow::Result;
use lazy_static::lazy_static;
use turbo_tasks::primitives::StringVc;
use turbo_tasks_fs::glob::GlobVc;
use turbopack_binding::{
turbo::tasks_fs::FileSystemPathVc,
Expand All @@ -16,9 +17,28 @@ use turbopack_binding::{
},
};

use crate::next_telemetry::ModuleFeatureTelemetry;

lazy_static! {
static ref UNSUPPORTED_PACKAGES: HashSet<&'static str> = ["@vercel/og"].into();
static ref UNSUPPORTED_PACKAGE_PATHS: HashSet<(&'static str, &'static str)> = [].into();
// Set of the features we want to track, following existing references in webpack/plugins/telemetry-plugin.
static ref FEATURE_MODULES: HashMap<&'static str, Vec<&'static str>> = HashMap::from([
(
"next",
vec![
"/image",
"future/image",
"legacy/image",
"/script",
"/dynamic",
"/font/google",
"/font/local"
]
),
("@next", vec!["/font/google", "/font/local"])
])
.into();
}

#[turbo_tasks::value]
Expand Down Expand Up @@ -83,3 +103,62 @@ impl ResolvePlugin for UnsupportedModulesResolvePlugin {
Ok(ResolveResultOptionVc::none())
}
}

/// A resolver plugin trackes the usage of certain import paths, emit a
/// telemetry event if there is a match.
#[turbo_tasks::value]
pub(crate) struct ModuleFeatureReportResolvePlugin {
root: FileSystemPathVc,
event_name: StringVc,
}

#[turbo_tasks::value_impl]
impl ModuleFeatureReportResolvePluginVc {
#[turbo_tasks::function]
pub fn new(root: FileSystemPathVc, event_name: StringVc) -> Self {
ModuleFeatureReportResolvePlugin { root, event_name }.cell()
}
}

#[turbo_tasks::value_impl]
impl ResolvePlugin for ModuleFeatureReportResolvePlugin {
#[turbo_tasks::function]
fn after_resolve_condition(&self) -> ResolvePluginConditionVc {
ResolvePluginConditionVc::new(self.root.root(), GlobVc::new("**"))
}

#[turbo_tasks::function]
async fn after_resolve(
&self,
_fs_path: FileSystemPathVc,
_context: FileSystemPathVc,
request: RequestVc,
) -> Result<ResolveResultOptionVc> {
if let Request::Module {
module,
path,
query: _,
} = &*request.await?
{
let feature_module = FEATURE_MODULES.get(module.as_str());
if let Some(feature_module) = feature_module {
let sub_path = feature_module
.iter()
.find(|sub_path| path.is_match(sub_path));

if let Some(sub_path) = sub_path {
ModuleFeatureTelemetry {
event_name: self.event_name.await?.to_string(),
feature_name: format!("{}{}", module, sub_path),
invocation_count: 1,
}
.cell()
.as_next_telemetry()
.emit();
}
}
}

Ok(ResolveResultOptionVc::none())
}
}
48 changes: 48 additions & 0 deletions packages/next-swc/crates/next-core/src/next_telemetry.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use anyhow::Result;
use turbo_tasks::{emit, primitives::StringVc, ValueToString, ValueToStringVc};

#[turbo_tasks::value_trait]
pub trait NextTelemetry {
fn event_name(&self) -> StringVc;
}

impl NextTelemetryVc {
pub fn emit(self) {
emit(self);
}
}

/// A struct represent telemetry event for feature usage,
/// referred as `importing` a certain module.
#[turbo_tasks::value(shared)]
pub struct ModuleFeatureTelemetry {
pub event_name: String,
pub feature_name: String,
pub invocation_count: usize,
}

impl ModuleFeatureTelemetryVc {
pub fn new(name: String, feature: String, invocation_count: usize) -> Self {
Self::cell(ModuleFeatureTelemetry {
event_name: name,
feature_name: feature,
invocation_count,
})
}
}

#[turbo_tasks::value_impl]
impl ValueToString for ModuleFeatureTelemetry {
#[turbo_tasks::function]
fn to_string(&self) -> StringVc {
StringVc::cell(format!("{},{}", self.event_name, self.feature_name))
}
}

#[turbo_tasks::value_impl]
impl NextTelemetry for ModuleFeatureTelemetry {
#[turbo_tasks::function]
async fn event_name(&self) -> Result<StringVc> {
Ok(StringVc::cell(self.event_name.clone()))
}
}

0 comments on commit 29be469

Please sign in to comment.