refactor: put lsp tracing behind flag (#28118)

To reduce binary size impact

---------

Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
This commit is contained in:
Nathan Whitaker 2025-02-14 17:17:52 +00:00 committed by GitHub
parent 979e2f7158
commit 56f67b5851
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 364 additions and 192 deletions

View file

@ -1129,6 +1129,33 @@ const ci = {
},
]),
},
"check-lsp-tracing": {
name: "check lsp tracing",
needs: ["pre_build"],
if: "${{ needs.pre_build.outputs.skip_build != 'true' }}",
"runs-on": ubuntuX86Runner,
"timeout-minutes": 30,
steps: skipJobsIfPrAndMarkedSkip([
...cloneRepoStep,
installRustStep,
{
// Restore cache from the latest 'main' branch build.
name: "Restore cache build output (PR)",
uses: "actions/cache/restore@v4",
if:
"github.ref != 'refs/heads/main' && !startsWith(github.ref, 'refs/tags/')",
with: {
path: prCachePath,
key: "never_saved",
"restore-keys": prCacheKeyPrefix,
},
},
{
name: "Check",
run: "cargo check -p deno --features=lsp-tracing",
},
]),
},
"publish-canary": {
name: "publish canary",
"runs-on": ubuntuX86Runner,

View file

@ -725,6 +725,42 @@ jobs:
- name: Cargo build
run: cargo build --target wasm32-unknown-unknown -p deno_resolver
if: '!(matrix.skip)'
check-lsp-tracing:
name: check lsp tracing
needs:
- pre_build
if: '${{ needs.pre_build.outputs.skip_build != ''true'' }}'
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- name: Configure git
run: |-
git config --global core.symlinks true
git config --global fetch.parallel 32
if: '!(matrix.skip)'
- name: Clone repository
uses: actions/checkout@v4
with:
fetch-depth: 5
submodules: false
if: '!(matrix.skip)'
- uses: dsherret/rust-toolchain-file@v1
if: '!(matrix.skip)'
- name: Restore cache build output (PR)
uses: actions/cache/restore@v4
if: '!(matrix.skip) && (github.ref != ''refs/heads/main'' && !startsWith(github.ref, ''refs/tags/''))'
with:
path: |-
./target
!./target/*/gn_out
!./target/*/gn_root
!./target/*/*.zip
!./target/*/*.tar.gz
key: never_saved
restore-keys: '40-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-'
- name: Check
run: cargo check -p deno --features=lsp-tracing
if: '!(matrix.skip)'
publish-canary:
name: publish canary
runs-on: ubuntu-24.04

View file

@ -47,6 +47,7 @@ upgrade = []
hmr = ["deno_runtime/hmr", "deno_snapshots/disable"]
# Vendor zlib as zlib-ng
__vendored_zlib_ng = ["flate2/zlib-ng-compat", "libz-sys/zlib-ng"]
lsp-tracing = ["dep:tracing", "dep:tracing-subscriber", "dep:tracing-opentelemetry"]
[build-dependencies]
deno_runtime = { workspace = true, features = ["include_js_files_for_snapshotting", "only_snapshotted_js_sources"] }
@ -172,9 +173,9 @@ tokio.workspace = true
tokio-util.workspace = true
tower.workspace = true
tower-lsp.workspace = true
tracing = { version = "0.1", features = ["log"] }
tracing-opentelemetry = "0.28.0"
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
tracing = { version = "0.1", features = ["log"], optional = true }
tracing-opentelemetry = { version = "0.28.0", optional = true }
tracing-subscriber = { version = "0.3.19", features = ["env-filter"], optional = true }
twox-hash.workspace = true
typed-arena = "=2.0.2"
unicode-width = "0.1.3"

View file

@ -150,7 +150,7 @@ fn to_narrow_lsp_range(
/// completion response, which will be valid import completions for the specific
/// context.
#[allow(clippy::too_many_arguments)]
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn get_import_completions(
specifier: &ModuleSpecifier,
position: &lsp::Position,

View file

@ -1297,7 +1297,7 @@ impl Documents {
/// For a given set of string specifiers, resolve each one from the graph,
/// for a given referrer. This is used to provide resolution information to
/// tsc when type checking.
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub fn resolve(
&self,
// (is_cjs: bool, raw_specifier: String)
@ -1556,7 +1556,7 @@ impl Documents {
self.dirty = false;
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub fn resolve_dependency(
&self,
specifier: &ModuleSpecifier,

View file

@ -248,7 +248,7 @@ impl LanguageServer {
/// Similar to `deno install --entrypoint` on the command line, where modules will be cached
/// in the Deno cache, including any of their dependencies.
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn cache(
&self,
specifiers: Vec<ModuleSpecifier>,
@ -434,7 +434,7 @@ impl LanguageServer {
}
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn refresh_configuration(&self) {
let (folders, capable) = {
let inner = self.inner.read().await;
@ -532,7 +532,7 @@ impl Inner {
/// Searches assets and documents for the provided
/// specifier erroring if it doesn't exist.
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub fn get_asset_or_document(
&self,
specifier: &ModuleSpecifier,
@ -559,7 +559,7 @@ impl Inner {
}
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn get_navigation_tree(
&self,
specifier: &ModuleSpecifier,
@ -623,7 +623,7 @@ impl Inner {
}
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub fn snapshot(&self) -> Arc<StateSnapshot> {
Arc::new(StateSnapshot {
project_version: self.project_version,
@ -667,7 +667,7 @@ impl Inner {
});
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn update_global_cache(&mut self) {
let mark = self.performance.mark("lsp.update_global_cache");
let maybe_cache = self.config.workspace_settings().cache.as_ref();
@ -725,7 +725,7 @@ impl Inner {
self.performance.measure(mark);
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub fn update_cache(&mut self) {
let mark = self.performance.mark("lsp.update_cache");
self.cache.update_config(&self.config);
@ -854,7 +854,7 @@ impl Inner {
})
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
fn walk_workspace(config: &Config) -> (IndexSet<ModuleSpecifier>, bool) {
if !config.workspace_capable() {
log::debug!("Skipped workspace walk due to client incapability.");
@ -1014,7 +1014,7 @@ impl Inner {
self.workspace_files_hash = enable_settings_hash;
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn refresh_config_tree(&mut self) {
let file_fetcher = CliFileFetcher::new(
self.cache.global().clone(),
@ -1070,7 +1070,7 @@ impl Inner {
}
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn refresh_resolver(&mut self) {
self.resolver = Arc::new(
LspResolver::from_config(
@ -1082,7 +1082,7 @@ impl Inner {
);
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn refresh_documents_config(&mut self) {
self.documents.update_config(
&self.config,
@ -1098,7 +1098,7 @@ impl Inner {
self.project_changed([], true);
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn did_open(&mut self, params: DidOpenTextDocumentParams) {
let mark = self.performance.mark_with_args("lsp.did_open", &params);
let Some(scheme) = params.text_document.uri.scheme() else {
@ -1148,7 +1148,7 @@ impl Inner {
self.performance.measure(mark);
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn did_change(&mut self, params: DidChangeTextDocumentParams) {
let mark = self.performance.mark_with_args("lsp.did_change", &params);
let specifier = self
@ -1186,7 +1186,7 @@ impl Inner {
self.performance.measure(mark);
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
fn did_save(&mut self, params: DidSaveTextDocumentParams) {
let _mark = self.performance.measure_scope("lsp.did_save");
let specifier = self
@ -1215,7 +1215,7 @@ impl Inner {
}));
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn refresh_dep_info(&mut self) {
let dep_info_by_scope = self.documents.dep_info_by_scope();
self
@ -1224,7 +1224,7 @@ impl Inner {
.await;
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn did_close(&mut self, params: DidCloseTextDocumentParams) {
let mark = self.performance.mark_with_args("lsp.did_close", &params);
let Some(scheme) = params.text_document.uri.scheme() else {
@ -1251,7 +1251,7 @@ impl Inner {
self.performance.measure(mark);
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn did_change_configuration(
&mut self,
params: DidChangeConfigurationParams,
@ -1284,7 +1284,7 @@ impl Inner {
self.send_testing_update();
}
#[tracing::instrument(skip(self))]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip(self)))]
async fn did_change_watched_files(
&mut self,
params: DidChangeWatchedFilesParams,
@ -1370,7 +1370,7 @@ impl Inner {
self.performance.measure(mark);
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn document_symbol(
&self,
params: DocumentSymbolParams,
@ -1423,7 +1423,7 @@ impl Inner {
Ok(response)
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn formatting(
&self,
params: DocumentFormattingParams,
@ -1538,7 +1538,7 @@ impl Inner {
}
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn hover(
&self,
params: HoverParams,
@ -1638,7 +1638,7 @@ impl Inner {
Ok(hover)
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
fn resolution_to_hover_text(
&self,
@ -1682,7 +1682,7 @@ impl Inner {
}
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn code_action(
&self,
params: CodeActionParams,
@ -1942,7 +1942,7 @@ impl Inner {
Ok(response)
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn code_action_resolve(
&self,
params: CodeAction,
@ -2109,7 +2109,7 @@ impl Inner {
)
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn code_lens(
&self,
params: CodeLensParams,
@ -2194,7 +2194,7 @@ impl Inner {
Ok(Some(code_lenses))
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn code_lens_resolve(
&self,
code_lens: CodeLens,
@ -2223,7 +2223,7 @@ impl Inner {
result
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn document_highlight(
&self,
params: DocumentHighlightParams,
@ -2290,7 +2290,7 @@ impl Inner {
Ok(document_highlights)
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn references(
&self,
params: ReferenceParams,
@ -2356,7 +2356,7 @@ impl Inner {
}
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn goto_definition(
&self,
params: GotoDefinitionParams,
@ -2416,7 +2416,7 @@ impl Inner {
}
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn goto_type_definition(
&self,
params: GotoTypeDefinitionParams,
@ -2479,7 +2479,7 @@ impl Inner {
Ok(response)
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn completion(
&self,
params: CompletionParams,
@ -2606,7 +2606,7 @@ impl Inner {
Ok(response)
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn completion_resolve(
&self,
params: CompletionItem,
@ -2695,7 +2695,7 @@ impl Inner {
Ok(completion_item)
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn goto_implementation(
&self,
params: GotoImplementationParams,
@ -2757,7 +2757,7 @@ impl Inner {
Ok(result)
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn folding_range(
&self,
params: FoldingRangeParams,
@ -2818,7 +2818,7 @@ impl Inner {
Ok(response)
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn incoming_calls(
&self,
params: CallHierarchyIncomingCallsParams,
@ -2877,7 +2877,7 @@ impl Inner {
Ok(Some(resolved_items))
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn outgoing_calls(
&self,
params: CallHierarchyOutgoingCallsParams,
@ -2938,7 +2938,7 @@ impl Inner {
Ok(Some(resolved_items))
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn prepare_call_hierarchy(
&self,
params: CallHierarchyPrepareParams,
@ -3016,7 +3016,7 @@ impl Inner {
Ok(response)
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn rename(
&self,
params: RenameParams,
@ -3077,7 +3077,7 @@ impl Inner {
}
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn selection_range(
&self,
params: SelectionRangeParams,
@ -3132,7 +3132,7 @@ impl Inner {
Ok(Some(selection_ranges))
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn semantic_tokens_full(
&self,
params: SemanticTokensParams,
@ -3199,7 +3199,7 @@ impl Inner {
Ok(response)
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn semantic_tokens_range(
&self,
params: SemanticTokensRangeParams,
@ -3264,7 +3264,7 @@ impl Inner {
Ok(response)
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn signature_help(
&self,
params: SignatureHelpParams,
@ -3339,7 +3339,7 @@ impl Inner {
}
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn will_rename_files(
&self,
params: RenameFilesParams,
@ -3401,7 +3401,7 @@ impl Inner {
file_text_changes_to_workspace_edit(&changes, self, token)
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn symbol(
&self,
params: WorkspaceSymbolParams,
@ -3453,7 +3453,7 @@ impl Inner {
Ok(maybe_symbol_information)
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
fn project_changed<'a>(
&mut self,
@ -3476,7 +3476,7 @@ impl Inner {
);
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
fn send_diagnostics_update(&self) {
let snapshot = DiagnosticServerUpdateMessage {
snapshot: self.snapshot(),
@ -4129,7 +4129,7 @@ impl Inner {
registrations
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
fn prepare_cache(
&mut self,
@ -4209,7 +4209,7 @@ impl Inner {
})
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn post_cache(&mut self) {
self.resolver.did_cache();
self.refresh_dep_info().await;
@ -4220,7 +4220,7 @@ impl Inner {
self.send_testing_update();
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
fn pre_did_change_workspace_folders(
&mut self,
@ -4250,7 +4250,7 @@ impl Inner {
self.config.set_workspace_folders(workspace_folders);
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn post_did_change_workspace_folders(&mut self) {
self.refresh_workspace_files();
self.refresh_config_tree().await;
@ -4330,7 +4330,7 @@ impl Inner {
Ok(result)
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
async fn inlay_hint(
&self,
params: InlayHintParams,

View file

@ -162,6 +162,32 @@ macro_rules! lsp_debug {
)
}
macro_rules! lsp_tracing_info_span {
($($arg:tt)*) => {{
#[cfg(feature = "lsp-tracing")]
{
::tracing::info_span!($($arg)*)
}
#[cfg(not(feature = "lsp-tracing"))]
{
$crate::lsp::trace::Span {}
}
}};
}
macro_rules! lsp_tracing_info {
($($arg:tt)*) => {
#[cfg(feature = "lsp-tracing")]
{
::tracing::info!($($arg)*);
}
#[cfg(not(feature = "lsp-tracing"))]
{}
};
}
pub(super) use lsp_debug;
pub(super) use lsp_log;
pub(super) use lsp_tracing_info;
pub(super) use lsp_tracing_info_span;
pub(super) use lsp_warn;

View file

@ -601,7 +601,7 @@ impl ModuleRegistry {
/// For a string specifier from the client, provide a set of completions, if
/// any, for the specifier.
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn get_completions(
&self,
text: &str,

View file

@ -2,43 +2,23 @@
use std::fmt;
use deno_core::anyhow;
use opentelemetry::trace::TracerProvider;
use opentelemetry::KeyValue;
use opentelemetry_otlp::WithExportConfig;
use opentelemetry_sdk::Resource;
use opentelemetry_semantic_conventions::resource::SERVICE_NAME;
#[cfg(feature = "lsp-tracing")]
pub use real_tracing::*;
use serde::Deserialize;
use serde::Serialize;
use tracing::level_filters::LevelFilter;
use tracing_opentelemetry::OpenTelemetryLayer;
use tracing_subscriber::fmt::format::FmtSpan;
use tracing_subscriber::layer::SubscriberExt;
#[cfg(not(feature = "lsp-tracing"))]
pub use stub_tracing::*;
use crate::lsp::logging::lsp_debug;
pub(crate) struct TracingGuard {
#[allow(dead_code)]
guard: (),
pub(crate) fn make_tracer(
endpoint: Option<&str>,
) -> Result<opentelemetry_sdk::trace::Tracer, anyhow::Error> {
let endpoint = endpoint.unwrap_or("http://localhost:4317");
let exporter = opentelemetry_otlp::SpanExporter::builder()
.with_tonic()
.with_endpoint(endpoint)
.build()?;
let provider = opentelemetry_sdk::trace::Builder::default()
.with_batch_exporter(exporter, opentelemetry_sdk::runtime::Tokio)
.with_resource(Resource::new(vec![KeyValue::new(SERVICE_NAME, "deno-lsp")]))
.build();
opentelemetry::global::set_tracer_provider(provider.clone());
Ok(provider.tracer("deno-lsp-tracer"))
}
pub(crate) struct TracingGuard(
// TODO(nathanwhit): use default guard here so we can change tracing after init
// but needs wiring through the subscriber to the TSC thread, as it can't be a global default
// #[allow(dead_code)] tracing::dispatcher::DefaultGuard,
#[allow(dead_code)] (),
);
#[allow(dead_code)]
defused: bool,
}
impl fmt::Debug for TracingGuard {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@ -46,12 +26,146 @@ impl fmt::Debug for TracingGuard {
}
}
impl Drop for TracingGuard {
fn drop(&mut self) {
lsp_debug!("Shutting down tracing");
tokio::task::spawn_blocking(|| {
opentelemetry::global::shutdown_tracer_provider()
});
#[cfg(feature = "lsp-tracing")]
mod real_tracing {
use deno_core::anyhow;
use opentelemetry::trace::TracerProvider;
pub use opentelemetry::Context;
use opentelemetry::KeyValue;
use opentelemetry_otlp::WithExportConfig;
use opentelemetry_sdk::Resource;
use opentelemetry_semantic_conventions::resource::SERVICE_NAME;
use tracing::level_filters::LevelFilter;
pub use tracing::span::EnteredSpan;
pub use tracing::Span;
use tracing_opentelemetry::OpenTelemetryLayer;
pub use tracing_opentelemetry::OpenTelemetrySpanExt as SpanExt;
use tracing_subscriber::fmt::format::FmtSpan;
use tracing_subscriber::layer::SubscriberExt;
use super::TracingCollector;
use super::TracingConfig;
use super::TracingGuard;
pub(crate) fn make_tracer(
endpoint: Option<&str>,
) -> Result<opentelemetry_sdk::trace::Tracer, anyhow::Error> {
let endpoint = endpoint.unwrap_or("http://localhost:4317");
let exporter = opentelemetry_otlp::SpanExporter::builder()
.with_tonic()
.with_endpoint(endpoint)
.build()?;
let provider = opentelemetry_sdk::trace::Builder::default()
.with_batch_exporter(exporter, opentelemetry_sdk::runtime::Tokio)
.with_resource(Resource::new(vec![KeyValue::new(
SERVICE_NAME,
"deno-lsp",
)]))
.build();
opentelemetry::global::set_tracer_provider(provider.clone());
Ok(provider.tracer("deno-lsp-tracer"))
}
pub(crate) fn init_tracing_subscriber(
config: &TracingConfig,
) -> Result<TracingGuard, anyhow::Error> {
if !config.enable {
return Err(anyhow::anyhow!("Tracing is not enabled"));
}
let filter = tracing_subscriber::EnvFilter::builder()
.with_default_directive(LevelFilter::INFO.into());
let filter = if let Some(directive) = config.filter.as_ref() {
filter.parse(directive)?
} else {
filter.with_env_var("DENO_LSP_TRACE").from_env()?
};
let open_telemetry_layer = match config.collector {
TracingCollector::OpenTelemetry => Some(OpenTelemetryLayer::new(
make_tracer(config.collector_endpoint.as_deref())?,
)),
_ => None,
};
let logging_layer = match config.collector {
TracingCollector::Logging => Some(
tracing_subscriber::fmt::layer()
.with_writer(std::io::stderr)
// Include span events in the log output.
// Without this, only events get logged (and at the moment we have none).
.with_span_events(FmtSpan::NEW | FmtSpan::CLOSE),
),
_ => None,
};
tracing::subscriber::set_global_default(
tracing_subscriber::registry()
.with(filter)
.with(logging_layer)
.with(open_telemetry_layer),
)
.unwrap();
let guard = ();
Ok(TracingGuard {
guard,
defused: false,
})
}
impl Drop for TracingGuard {
fn drop(&mut self) {
if !self.defused {
crate::lsp::logging::lsp_debug!("Shutting down tracing");
tokio::task::spawn_blocking(|| {
opentelemetry::global::shutdown_tracer_provider()
});
}
}
}
}
#[cfg(not(feature = "lsp-tracing"))]
mod stub_tracing {
pub trait SpanExt {
#[allow(dead_code)]
fn set_parent(&self, _context: Context);
fn context(&self) -> Context;
}
#[derive(Debug, Clone)]
pub struct Span {}
impl SpanExt for Span {
#[allow(dead_code)]
fn set_parent(&self, _context: Context) {}
fn context(&self) -> Context {
Context {}
}
}
impl Span {
pub fn entered(self) -> EnteredSpan {
EnteredSpan {}
}
pub fn current() -> Self {
Self {}
}
}
#[derive(Debug)]
pub struct EnteredSpan {}
#[derive(Clone, Debug)]
pub struct Context {}
pub(crate) fn init_tracing_subscriber(
_config: &super::TracingConfig,
) -> Result<super::TracingGuard, deno_core::anyhow::Error> {
Ok(super::TracingGuard {
defused: false,
guard: {},
})
}
}
@ -115,45 +229,3 @@ impl TracingConfigOrEnabled {
}
}
}
pub(crate) fn init_tracing_subscriber(
config: &TracingConfig,
) -> Result<TracingGuard, anyhow::Error> {
if !config.enable {
return Err(anyhow::anyhow!("Tracing is not enabled"));
}
let filter = tracing_subscriber::EnvFilter::builder()
.with_default_directive(LevelFilter::INFO.into());
let filter = if let Some(directive) = config.filter.as_ref() {
filter.parse(directive)?
} else {
filter.with_env_var("DENO_LSP_TRACE").from_env()?
};
let open_telemetry_layer = match config.collector {
TracingCollector::OpenTelemetry => Some(OpenTelemetryLayer::new(
make_tracer(config.collector_endpoint.as_deref())?,
)),
_ => None,
};
let logging_layer = match config.collector {
TracingCollector::Logging => Some(
tracing_subscriber::fmt::layer()
.with_writer(std::io::stderr)
// Include span events in the log output.
// Without this, only events get logged (and at the moment we have none).
.with_span_events(FmtSpan::NEW | FmtSpan::CLOSE),
),
_ => None,
};
tracing::subscriber::set_global_default(
tracing_subscriber::registry()
.with(filter)
.with(logging_layer)
.with(open_telemetry_layer),
)
.unwrap();
let guard = ();
Ok(TracingGuard(guard))
}

View file

@ -68,7 +68,6 @@ use tokio_util::sync::CancellationToken;
use tower_lsp::jsonrpc::Error as LspError;
use tower_lsp::jsonrpc::Result as LspResult;
use tower_lsp::lsp_types as lsp;
use tracing_opentelemetry::OpenTelemetrySpanExt;
use super::analysis::CodeActionData;
use super::code_lens;
@ -128,7 +127,7 @@ type Request = (
oneshot::Sender<Result<String, AnyError>>,
CancellationToken,
Option<PendingChange>,
Option<opentelemetry::Context>,
Option<super::trace::Context>,
);
#[derive(Debug, Clone, Copy, Serialize_repr)]
@ -482,7 +481,7 @@ impl TsServer {
}
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn get_diagnostics(
&self,
snapshot: Arc<StateSnapshot>,
@ -548,7 +547,7 @@ impl TsServer {
Ok((diagnostics_map, ambient_modules_by_scope))
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn cleanup_semantic_cache(&self, snapshot: Arc<StateSnapshot>) {
for scope in snapshot
.config
@ -575,7 +574,7 @@ impl TsServer {
}
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn find_references(
&self,
snapshot: Arc<StateSnapshot>,
@ -630,7 +629,7 @@ impl TsServer {
Ok(Some(all_symbols.into_iter().collect()))
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn get_navigation_tree(
&self,
snapshot: Arc<StateSnapshot>,
@ -644,7 +643,7 @@ impl TsServer {
self.request(snapshot, req, scope, token).await
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn get_supported_code_fixes(
&self,
snapshot: Arc<StateSnapshot>,
@ -659,7 +658,7 @@ impl TsServer {
})
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn get_quick_info(
&self,
snapshot: Arc<StateSnapshot>,
@ -676,7 +675,7 @@ impl TsServer {
}
#[allow(clippy::too_many_arguments)]
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn get_code_fixes(
&self,
snapshot: Arc<StateSnapshot>,
@ -708,7 +707,7 @@ impl TsServer {
}
#[allow(clippy::too_many_arguments)]
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn get_applicable_refactors(
&self,
snapshot: Arc<StateSnapshot>,
@ -741,7 +740,7 @@ impl TsServer {
})
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn get_combined_code_fix(
&self,
snapshot: Arc<StateSnapshot>,
@ -770,7 +769,7 @@ impl TsServer {
}
#[allow(clippy::too_many_arguments)]
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn get_edits_for_refactor(
&self,
snapshot: Arc<StateSnapshot>,
@ -800,7 +799,7 @@ impl TsServer {
})
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn get_edits_for_file_rename(
&self,
snapshot: Arc<StateSnapshot>,
@ -859,7 +858,7 @@ impl TsServer {
Ok(all_changes.into_iter().collect())
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn get_document_highlights(
&self,
snapshot: Arc<StateSnapshot>,
@ -880,7 +879,7 @@ impl TsServer {
self.request(snapshot, req, scope, token).await
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn get_definition(
&self,
snapshot: Arc<StateSnapshot>,
@ -906,7 +905,7 @@ impl TsServer {
})
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn get_type_definition(
&self,
snapshot: Arc<StateSnapshot>,
@ -934,7 +933,7 @@ impl TsServer {
}
#[allow(clippy::too_many_arguments)]
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn get_completions(
&self,
snapshot: Arc<StateSnapshot>,
@ -962,7 +961,7 @@ impl TsServer {
})
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn get_completion_details(
&self,
snapshot: Arc<StateSnapshot>,
@ -990,7 +989,7 @@ impl TsServer {
})
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn get_implementations(
&self,
snapshot: Arc<StateSnapshot>,
@ -1045,7 +1044,7 @@ impl TsServer {
Ok(Some(all_locations.into_iter().collect()))
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn get_outlining_spans(
&self,
snapshot: Arc<StateSnapshot>,
@ -1059,7 +1058,7 @@ impl TsServer {
self.request(snapshot, req, scope, token).await
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn provide_call_hierarchy_incoming_calls(
&self,
snapshot: Arc<StateSnapshot>,
@ -1108,7 +1107,7 @@ impl TsServer {
Ok(all_calls.into_iter().collect())
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn provide_call_hierarchy_outgoing_calls(
&self,
snapshot: Arc<StateSnapshot>,
@ -1135,7 +1134,7 @@ impl TsServer {
})
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn prepare_call_hierarchy(
&self,
snapshot: Arc<StateSnapshot>,
@ -1169,7 +1168,7 @@ impl TsServer {
})
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn find_rename_locations(
&self,
snapshot: Arc<StateSnapshot>,
@ -1227,7 +1226,7 @@ impl TsServer {
Ok(Some(all_locations.into_iter().collect()))
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn get_smart_selection_range(
&self,
snapshot: Arc<StateSnapshot>,
@ -1243,7 +1242,7 @@ impl TsServer {
self.request(snapshot, req, scope, token).await
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn get_encoded_semantic_classifications(
&self,
snapshot: Arc<StateSnapshot>,
@ -1263,7 +1262,7 @@ impl TsServer {
self.request(snapshot, req, scope, token).await
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn get_signature_help_items(
&self,
snapshot: Arc<StateSnapshot>,
@ -1281,7 +1280,7 @@ impl TsServer {
self.request(snapshot, req, scope, token).await
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn get_navigate_to_items(
&self,
snapshot: Arc<StateSnapshot>,
@ -1333,7 +1332,7 @@ impl TsServer {
Ok(all_items.into_iter().collect())
}
#[tracing::instrument(skip_all)]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all))]
pub async fn provide_inlay_hints(
&self,
snapshot: Arc<StateSnapshot>,
@ -1361,7 +1360,8 @@ impl TsServer {
where
R: de::DeserializeOwned,
{
let context = tracing::Span::current().context();
use super::trace::SpanExt;
let context = super::trace::Span::current().context();
let mark = self
.performance
.mark(format!("tsc.request.{}", req.method()));
@ -1386,7 +1386,7 @@ impl TsServer {
tokio::select! {
value = &mut rx => {
let value = value??;
let _span = tracing::info_span!("Tsc response deserialization");
let _span = super::logging::lsp_tracing_info_span!("Tsc response deserialization");
let r = Ok(serde_json::from_str(&value)?);
self.performance.measure(mark);
r
@ -3788,7 +3788,7 @@ impl CompletionInfo {
Ok(())
}
#[tracing::instrument(skip_all, fields(entries = %self.entries.len()))]
#[cfg_attr(feature = "lsp-tracing", tracing::instrument(skip_all, fields(entries = %self.entries.len())))]
pub fn as_completion_response(
&self,
line_index: Arc<LineIndex>,
@ -4509,7 +4509,7 @@ struct State {
token: CancellationToken,
pending_requests: Option<UnboundedReceiver<Request>>,
mark: Option<PerformanceMark>,
context: Option<opentelemetry::Context>,
context: Option<super::trace::Context>,
enable_tracing: Arc<AtomicBool>,
}
@ -4634,7 +4634,7 @@ fn op_load<'s>(
state: &mut OpState,
#[string] specifier: &str,
) -> Result<v8::Local<'s, v8::Value>, LoadError> {
let _span = tracing::info_span!("op_load").entered();
let _span = super::logging::lsp_tracing_info_span!("op_load").entered();
let state = state.borrow_mut::<State>();
let mark = state
.performance
@ -4666,7 +4666,7 @@ fn op_release(
state: &mut OpState,
#[string] specifier: &str,
) -> Result<(), deno_core::url::ParseError> {
let _span = tracing::info_span!("op_release").entered();
let _span = super::logging::lsp_tracing_info_span!("op_release").entered();
let state = state.borrow_mut::<State>();
let mark = state
.performance
@ -4685,7 +4685,7 @@ fn op_resolve(
#[string] base: String,
#[serde] specifiers: Vec<(bool, String)>,
) -> Result<Vec<Option<(String, Option<String>)>>, deno_core::url::ParseError> {
let _span = tracing::info_span!("op_resolve").entered();
let _span = super::logging::lsp_tracing_info_span!("op_resolve").entered();
op_resolve_inner(state, ResolveArgs { base, specifiers })
}
@ -4807,7 +4807,7 @@ fn op_respond(
#[string] response: String,
#[string] error: String,
) {
let _span = tracing::info_span!("op_respond").entered();
let _span = super::logging::lsp_tracing_info_span!("op_respond").entered();
let state = state.borrow_mut::<State>();
state.performance.measure(state.mark.take().unwrap());
state.last_scope = None;
@ -4825,31 +4825,43 @@ fn op_respond(
}
}
struct TracingSpan(#[allow(dead_code)] Option<tracing::span::EnteredSpan>);
struct TracingSpan(#[allow(dead_code)] Option<super::trace::EnteredSpan>);
deno_core::external!(TracingSpan, "lsp::TracingSpan");
fn span_with_context(
state: &State,
span: tracing::Span,
) -> tracing::span::EnteredSpan {
if let Some(context) = &state.context {
span.set_parent(context.clone());
_state: &State,
span: super::trace::Span,
) -> super::trace::EnteredSpan {
#[cfg(feature = "lsp-tracing")]
{
use tracing_opentelemetry::OpenTelemetrySpanExt;
if let Some(context) = &_state.context {
span.set_parent(context.clone());
}
span.entered()
}
#[cfg(not(feature = "lsp-tracing"))]
{
span.entered()
}
span.entered()
}
#[op2(fast)]
fn op_make_span(
op_state: &mut OpState,
#[string] s: &str,
#[string] _s: &str,
needs_context: bool,
) -> *const c_void {
let state = op_state.borrow_mut::<State>();
if !state.tracing_enabled() {
return deno_core::ExternalPointer::new(TracingSpan(None)).into_raw();
}
let sp = tracing::info_span!("js", otel.name = format!("js::{s}").as_str());
let sp = super::logging::lsp_tracing_info_span!(
"js",
otel.name = format!("js::{_s}").as_str()
);
let span = if needs_context {
span_with_context(state, sp)
} else {
@ -4859,10 +4871,10 @@ fn op_make_span(
}
#[op2(fast)]
fn op_log_event(op_state: &OpState, #[string] msg: &str) {
fn op_log_event(op_state: &OpState, #[string] _msg: &str) {
let state = op_state.borrow::<State>();
if state.tracing_enabled() {
tracing::info!(msg = msg);
super::logging::lsp_tracing_info!(msg = _msg);
}
}
@ -4887,7 +4899,8 @@ struct ScriptNames {
#[op2]
#[serde]
fn op_script_names(state: &mut OpState) -> ScriptNames {
let _span = tracing::info_span!("op_script_names").entered();
let _span =
super::logging::lsp_tracing_info_span!("op_script_names").entered();
let state = state.borrow_mut::<State>();
let mark = state.performance.mark("tsc.op.op_script_names");
let mut result = ScriptNames {

View file

@ -1,9 +1,6 @@
[# This test is still downloading code, because we have a private registry]
[# that serves the same packages. The important bit is the message below.]
[WILDCARD] No .npmrc file found
[WILDCARD]
Download http://localhost:4260/@denotest%2fesm-basic
[WILDCARD]
Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz
[WILDCARD]
Initialize @denotest/esm-basic@1.0.0
[WILDCARD]No .npmrc file found
[WILDCARD]Download http://localhost:4260/@denotest%2fesm-basic
[WILDCARD]Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz
[WILDCARD]Initialize @denotest/esm-basic@1.0.0