Skip to content

Commit

Permalink
feat(turbopack): emits modulefeature telemetry
Browse files Browse the repository at this point in the history
  • Loading branch information
kwonoj committed Jul 21, 2023
1 parent 3e34b9f commit 92e8c71
Show file tree
Hide file tree
Showing 9 changed files with 202 additions and 28 deletions.
20 changes: 12 additions & 8 deletions packages/next-swc/crates/napi/src/next_api/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ use next_api::route::{Endpoint, WrittenEndpoint};
use turbo_tasks::Vc;
use turbopack_binding::turbopack::core::error::PrettyPrintError;

use super::utils::{get_issues, subscribe, NapiIssue, RootTask, TurbopackResult, VcArc};
use super::utils::{
get_diagnostics, get_issues, subscribe, NapiDiagnostic, NapiIssue, RootTask, TurbopackResult,
VcArc,
};

#[napi(object)]
#[derive(Default)]
Expand Down Expand Up @@ -71,20 +74,21 @@ pub async fn endpoint_write_to_disk(
) -> napi::Result<TurbopackResult<NapiWrittenEndpoint>> {
let turbo_tasks = endpoint.turbo_tasks().clone();
let endpoint = ***endpoint;
let (written, issues) = turbo_tasks
let (written, issues, diags) = turbo_tasks
.run_once(async move {
let write_to_disk = endpoint.write_to_disk();
let issues = get_issues(write_to_disk).await?;
let diags = get_diagnostics(write_to_disk).await?;
let written = write_to_disk.strongly_consistent().await?;
Ok((written, issues))
Ok((written, issues, diags))
})
.await
.map_err(|e| napi::Error::from_reason(PrettyPrintError(&e).to_string()))?;
// TODO diagnostics
Ok(TurbopackResult {
result: NapiWrittenEndpoint::from(&*written),
issues: issues.iter().map(|i| NapiIssue::from(&**i)).collect(),
diagnostics: vec![],
diagnostics: diags.iter().map(|d| NapiDiagnostic::from(d)).collect(),
})
}

Expand All @@ -103,16 +107,16 @@ pub fn endpoint_changed_subscribe(
move || async move {
let changed = endpoint.changed();
let issues = get_issues(changed).await?;
let diags = get_diagnostics(changed).await?;
changed.await?;
// TODO diagnostics
Ok(issues)
Ok((issues, diags))
},
|ctx| {
let issues = ctx.value;
let (issues, diags) = ctx.value;
Ok(vec![TurbopackResult {
result: (),
issues: issues.iter().map(|i| NapiIssue::from(&**i)).collect(),
diagnostics: vec![],
diagnostics: diags.iter().map(|d| NapiDiagnostic::from(d)).collect(),
}])
},
)
Expand Down
13 changes: 9 additions & 4 deletions packages/next-swc/crates/napi/src/next_api/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ use turbopack_binding::{
use super::{
endpoint::ExternalEndpoint,
utils::{
get_issues, serde_enum_to_string, subscribe, NapiDiagnostic, NapiIssue, RootTask, VcArc,
get_diagnostics, get_issues, serde_enum_to_string, subscribe, NapiDiagnostic, NapiIssue,
RootTask, VcArc,
},
};
use crate::register;
Expand Down Expand Up @@ -226,12 +227,16 @@ pub fn project_entrypoints_subscribe(
move || async move {
let entrypoints = project.entrypoints();
let issues = get_issues(entrypoints).await?;
let diags = get_diagnostics(entrypoints).await?;

let entrypoints = entrypoints.strongly_consistent().await?;

// TODO peek_issues and diagnostics
Ok((entrypoints, issues))
Ok((entrypoints, issues, diags))
},
move |ctx| {
let (entrypoints, issues) = ctx.value;
let (entrypoints, issues, diags) = ctx.value;

Ok(vec![NapiEntrypoints {
routes: entrypoints
.routes
Expand All @@ -249,7 +254,7 @@ pub fn project_entrypoints_subscribe(
.iter()
.map(|issue| NapiIssue::from(&**issue))
.collect(),
diagnostics: vec![],
diagnostics: diags.iter().map(|d| NapiDiagnostic::from(d)).collect(),
}])
},
)
Expand Down
38 changes: 35 additions & 3 deletions packages/next-swc/crates/napi/src/next_api/utils.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{future::Future, ops::Deref, sync::Arc};
use std::{collections::HashMap, future::Future, ops::Deref, sync::Arc};

use anyhow::{anyhow, Context, Result};
use napi::{
Expand All @@ -7,10 +7,11 @@ use napi::{
JsFunction, JsObject, JsUnknown, NapiRaw, NapiValue, Status,
};
use serde::Serialize;
use turbo_tasks::{unit, ReadRef, TaskId, TurboTasks, Vc};
use turbo_tasks::{unit, ReadRef, TaskId, TryJoinIterExt, TurboTasks, Vc};
use turbopack_binding::{
turbo::{tasks_fs::FileContent, tasks_memory::MemoryBackend},
turbopack::core::{
diagnostics::{Diagnostic, DiagnosticContextExt, PlainDiagnostic},
error::PrettyPrintError,
issue::{IssueContextExt, PlainIssue, PlainIssueSource, PlainSource},
source_pos::SourcePos,
Expand Down Expand Up @@ -85,6 +86,23 @@ pub async fn get_issues<T>(source: Vc<T>) -> Result<Vec<ReadRef<PlainIssue>>> {
issues.get_plain_issues().await
}

/// Collect [turbopack::core::diagnostics::Diagnostic] from given source,
/// returns [turbopack::core::diagnostics::PlainDiagnostic]
pub async fn get_diagnostics<T>(source: Vc<T>) -> Result<Vec<ReadRef<PlainDiagnostic>>> {
let captured_diags = source
.peek_diagnostics()
.await?
.strongly_consistent()
.await?;

captured_diags
.diagnostics
.iter()
.map(|d| d.into_plain())
.try_join()
.await
}

#[napi(object)]
pub struct NapiIssue {
pub severity: String,
Expand Down Expand Up @@ -178,7 +196,21 @@ impl From<SourcePos> for NapiSourcePos {
}

#[napi(object)]
pub struct NapiDiagnostic {}
pub struct NapiDiagnostic {
pub category: String,
pub name: String,
pub payload: HashMap<String, String>,
}

impl NapiDiagnostic {
pub fn from(diagnostic: &PlainDiagnostic) -> Self {
Self {
category: diagnostic.category.clone(),
name: diagnostic.name.clone(),
payload: diagnostic.payload.clone(),
}
}
}

pub struct TurbopackResult<T: ToNapiValue> {
pub result: T,
Expand Down
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 @@ -36,6 +36,7 @@ mod next_route_matcher;
pub mod next_server;
pub mod next_server_component;
pub mod next_shared;
pub mod next_telemetry;
mod page_loader;
mod page_source;
pub mod pages_structure;
Expand Down
9 changes: 5 additions & 4 deletions packages/next-swc/crates/next-core/src/next_client/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ use crate::{
get_next_client_resolved_map, mdx_import_source_file,
},
next_shared::{
resolve::UnsupportedModulesResolvePlugin,
resolve::{ModuleFeatureReportResolvePlugin, UnsupportedModulesResolvePlugin},
transforms::{
emotion::get_emotion_transform_plugin, get_relay_transform_plugin,
styled_components::get_styled_components_transform_plugin,
Expand Down Expand Up @@ -145,9 +145,10 @@ pub async fn get_client_resolve_options_context(
resolved_map: Some(next_client_resolved_map),
browser: true,
module: true,
plugins: vec![Vc::upcast(UnsupportedModulesResolvePlugin::new(
project_path,
))],
plugins: vec![
Vc::upcast(ModuleFeatureReportResolvePlugin::new(project_path)),
Vc::upcast(UnsupportedModulesResolvePlugin::new(project_path)),
],
..Default::default()
};
Ok(ResolveOptionsContext {
Expand Down
17 changes: 11 additions & 6 deletions packages/next-swc/crates/next-core/src/next_edge/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,13 @@ use turbopack_binding::{
};

use crate::{
mode::NextMode, next_client::context::get_client_assets_path, next_config::NextConfig,
next_import_map::get_next_edge_import_map, next_server::context::ServerContextType,
next_shared::resolve::UnsupportedModulesResolvePlugin, util::foreign_code_context_condition,
mode::NextMode,
next_client::context::get_client_assets_path,
next_config::NextConfig,
next_import_map::get_next_edge_import_map,
next_server::context::ServerContextType,
next_shared::resolve::{ModuleFeatureReportResolvePlugin, UnsupportedModulesResolvePlugin},
util::foreign_code_context_condition,
};

fn defines() -> CompileTimeDefines {
Expand Down Expand Up @@ -93,9 +97,10 @@ pub async fn get_edge_resolve_options_context(
import_map: Some(next_edge_import_map),
module: true,
browser: true,
plugins: vec![Vc::upcast(UnsupportedModulesResolvePlugin::new(
project_path,
))],
plugins: vec![
Vc::upcast(ModuleFeatureReportResolvePlugin::new(project_path)),
Vc::upcast(UnsupportedModulesResolvePlugin::new(project_path)),
],
..Default::default()
};

Expand Down
12 changes: 10 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 @@ -46,7 +46,7 @@ use crate::{
next_import_map::{get_next_server_import_map, mdx_import_source_file},
next_server::resolve::ExternalPredicate,
next_shared::{
resolve::UnsupportedModulesResolvePlugin,
resolve::{ModuleFeatureReportResolvePlugin, UnsupportedModulesResolvePlugin},
transforms::{
emotion::get_emotion_transform_plugin, get_relay_transform_plugin,
styled_components::get_styled_components_transform_plugin,
Expand Down Expand Up @@ -97,6 +97,7 @@ pub async fn get_server_resolve_options_context(
get_next_server_import_map(project_path, ty, mode, 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 = ModuleFeatureReportResolvePlugin::new(project_path);
let unsupported_modules_resolve_plugin = UnsupportedModulesResolvePlugin::new(project_path);
let server_component_externals_plugin = ExternalCjsModulesResolvePlugin::new(
project_path,
Expand All @@ -118,6 +119,7 @@ pub async fn get_server_resolve_options_context(
custom_conditions: vec![mode.node_env().to_string(), "node".to_string()],
import_map: Some(next_server_import_map),
plugins: vec![
Vc::upcast(module_feature_report_resolve_plugin),
Vc::upcast(external_cjs_modules_plugin),
Vc::upcast(unsupported_modules_resolve_plugin),
],
Expand Down Expand Up @@ -146,6 +148,7 @@ pub async fn get_server_resolve_options_context(
],
import_map: Some(next_server_import_map),
plugins: vec![
Vc::upcast(module_feature_report_resolve_plugin),
Vc::upcast(server_component_externals_plugin),
Vc::upcast(unsupported_modules_resolve_plugin),
],
Expand Down Expand Up @@ -175,6 +178,7 @@ pub async fn get_server_resolve_options_context(
],
import_map: Some(next_server_import_map),
plugins: vec![
Vc::upcast(module_feature_report_resolve_plugin),
Vc::upcast(server_component_externals_plugin),
Vc::upcast(unsupported_modules_resolve_plugin),
],
Expand All @@ -197,6 +201,7 @@ pub async fn get_server_resolve_options_context(
custom_conditions: vec![mode.node_env().to_string(), "node".to_string()],
import_map: Some(next_server_import_map),
plugins: vec![
Vc::upcast(module_feature_report_resolve_plugin),
Vc::upcast(server_component_externals_plugin),
Vc::upcast(unsupported_modules_resolve_plugin),
],
Expand All @@ -218,7 +223,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![Vc::upcast(unsupported_modules_resolve_plugin)],
plugins: vec![
Vc::upcast(module_feature_report_resolve_plugin),
Vc::upcast(unsupported_modules_resolve_plugin),
],
..Default::default()
};
ResolveOptionsContext {
Expand Down
74 changes: 73 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,4 +1,4 @@
use std::collections::HashSet;
use std::collections::{HashMap, HashSet};

use anyhow::Result;
use lazy_static::lazy_static;
Expand All @@ -7,6 +7,7 @@ use turbo_tasks_fs::glob::Glob;
use turbopack_binding::{
turbo::tasks_fs::FileSystemPath,
turbopack::core::{
diagnostics::DiagnosticExt,
issue::{unsupported_module::UnsupportedModuleIssue, IssueExt},
resolve::{
parse::Request,
Expand All @@ -17,9 +18,27 @@ 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"])
]);
}

#[turbo_tasks::value]
Expand Down Expand Up @@ -82,3 +101,56 @@ impl ResolvePlugin for UnsupportedModulesResolvePlugin {
Ok(ResolveResultOption::none())
}
}

/// A resolver plugin tracks the usage of certain import paths, emit
/// telemetry events if there is a match.
#[turbo_tasks::value]
pub(crate) struct ModuleFeatureReportResolvePlugin {
root: Vc<FileSystemPath>,
}

#[turbo_tasks::value_impl]
impl ModuleFeatureReportResolvePlugin {
#[turbo_tasks::function]
pub fn new(root: Vc<FileSystemPath>) -> Vc<Self> {
ModuleFeatureReportResolvePlugin { root }.cell()
}
}

#[turbo_tasks::value_impl]
impl ResolvePlugin for ModuleFeatureReportResolvePlugin {
#[turbo_tasks::function]
fn after_resolve_condition(&self) -> Vc<ResolvePluginCondition> {
ResolvePluginCondition::new(self.root.root(), Glob::new("**".to_string()))
}

#[turbo_tasks::function]
async fn after_resolve(
&self,
_fs_path: Vc<FileSystemPath>,
_context: Vc<FileSystemPath>,
request: Vc<Request>,
) -> Result<Vc<ResolveResultOption>> {
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::new(format!("{}{}", module, sub_path), 1)
.cell()
.emit();
}
}
}

Ok(ResolveResultOption::none())
}
}

0 comments on commit 92e8c71

Please sign in to comment.