mirror of
https://codeberg.org/icewind/logsmash.git
synced 2026-06-03 10:04:12 +02:00
group by route
This commit is contained in:
parent
a00565cf65
commit
e982a12df5
18 changed files with 2153 additions and 446 deletions
795
logging-extractor/Cargo.lock
generated
795
logging-extractor/Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -16,12 +16,14 @@ thiserror = "1.0.63"
|
|||
serde = { version = "1.0.204", features = ["derive"] }
|
||||
serde_json = "1.0.120"
|
||||
walkdir = "2.5.0"
|
||||
tree-sitter = "0.22.6"
|
||||
tree-sitter-php = "0.22.7"
|
||||
tree-sitter = "0.25.8"
|
||||
tree-sitter-php = "0.24.2"
|
||||
memchr = "2.7.4"
|
||||
databake = { version = "0.1.8", features = ["derive"] }
|
||||
regex = "1.10.5"
|
||||
sprintf = "0.3.1"
|
||||
nextcloud_appinfo = "0.6.0"
|
||||
nextcloud-route-extractor = { version = "0.1.0", git = "https://codeberg.org/icewind/nextcloud-route-extractor.git" }
|
||||
|
||||
[build-dependencies]
|
||||
cc = "1.1.6"
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use crate::messagebuilder::MessageBuilder;
|
|||
use crate::name_resolver::resolve_name;
|
||||
use crate::{LogLevel, LoggingStatement};
|
||||
use std::collections::HashMap;
|
||||
use tree_sitter::{Language, Node, Parser, Query, QueryCursor};
|
||||
use tree_sitter::{Language, Node, Parser, Query, QueryCursor, StreamingIterator};
|
||||
|
||||
pub struct LogExtractor {
|
||||
language: Language,
|
||||
|
|
@ -14,7 +14,7 @@ pub struct LogExtractor {
|
|||
|
||||
impl LogExtractor {
|
||||
pub fn new() -> Self {
|
||||
let language = tree_sitter_php::language_php();
|
||||
let language: Language = tree_sitter_php::LANGUAGE_PHP.into();
|
||||
let method_query = Query::new(
|
||||
&language,
|
||||
r#"(member_call_expression
|
||||
|
|
@ -36,8 +36,8 @@ impl LogExtractor {
|
|||
let use_query = Query::new(
|
||||
&language,
|
||||
r#"(namespace_use_clause
|
||||
[(name) (qualified_name)] @name
|
||||
(namespace_aliasing_clause (name) @alias)?
|
||||
(_) @name
|
||||
alias: (name)? @alias
|
||||
)"#,
|
||||
)
|
||||
.expect("invalid query");
|
||||
|
|
@ -67,7 +67,6 @@ impl LogExtractor {
|
|||
parser
|
||||
.set_language(&self.language)
|
||||
.expect("Error loading PHP grammar");
|
||||
parser.set_timeout_micros(10 * 1000 * 1000);
|
||||
|
||||
let tree = parser.parse(code, None).expect("parse timeout or canceled");
|
||||
|
||||
|
|
@ -116,24 +115,28 @@ impl LogExtractor {
|
|||
code: &'a str,
|
||||
node: Node<'a>,
|
||||
) -> impl Iterator<Item = LogCall<'a>> + 'a {
|
||||
let method_calls = cursor.matches(&self.method_query, node, code.as_bytes());
|
||||
let mut method_calls = cursor.matches(&self.method_query, node, code.as_bytes());
|
||||
|
||||
method_calls.filter_map(|method_call| {
|
||||
let mut results = vec![];
|
||||
while let Some(method_call) = method_calls.next() {
|
||||
let name = method_call.captures[0]
|
||||
.node
|
||||
.utf8_text(code.as_bytes())
|
||||
.unwrap_or("malformed utf8");
|
||||
let level = LogLevel::parse(name)?;
|
||||
let Some(level) = LogLevel::parse(name) else {
|
||||
continue;
|
||||
};
|
||||
let line = method_call.captures[0].node.start_position().row;
|
||||
|
||||
let arguments = method_call.captures[1].node;
|
||||
Some(LogCall {
|
||||
results.push(LogCall {
|
||||
level,
|
||||
line,
|
||||
arguments: arguments.named_child(0),
|
||||
exception: None,
|
||||
})
|
||||
})
|
||||
});
|
||||
}
|
||||
results.into_iter()
|
||||
}
|
||||
|
||||
fn get_throw_calls<'a>(
|
||||
|
|
@ -142,13 +145,14 @@ impl LogExtractor {
|
|||
code: &'a str,
|
||||
node: Node<'a>,
|
||||
) -> impl Iterator<Item = LogCall<'a>> + 'a {
|
||||
let throws = cursor.matches(&self.throw_query, node, code.as_bytes());
|
||||
let mut throws = cursor.matches(&self.throw_query, node, code.as_bytes());
|
||||
|
||||
throws.map(|method_call| {
|
||||
let mut results = vec![];
|
||||
while let Some(method_call) = throws.next() {
|
||||
let level = LogLevel::Exception;
|
||||
let arguments = method_call.captures[1].node;
|
||||
let line = arguments.start_position().row;
|
||||
LogCall {
|
||||
results.push(LogCall {
|
||||
level,
|
||||
line,
|
||||
arguments: arguments.named_child(0),
|
||||
|
|
@ -159,8 +163,9 @@ impl LogExtractor {
|
|||
.unwrap()
|
||||
.into(),
|
||||
),
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
results.into_iter()
|
||||
}
|
||||
|
||||
fn get_aliases<'a>(
|
||||
|
|
@ -169,29 +174,31 @@ impl LogExtractor {
|
|||
code: &'a str,
|
||||
node: Node<'a>,
|
||||
) -> HashMap<&'a str, &'a str> {
|
||||
let use_calls = cursor.matches(&self.use_query, node, code.as_bytes());
|
||||
let mut use_calls = cursor.matches(&self.use_query, node, code.as_bytes());
|
||||
|
||||
use_calls
|
||||
.map(|method_call| {
|
||||
let source = method_call.captures[0]
|
||||
.node
|
||||
.utf8_text(code.as_bytes())
|
||||
.unwrap_or("malformed utf8")
|
||||
.trim_start_matches('\\');
|
||||
let target = method_call
|
||||
.captures
|
||||
.get(1)
|
||||
.map(|capture| {
|
||||
capture
|
||||
.node
|
||||
.utf8_text(code.as_bytes())
|
||||
.expect("invalid utf8")
|
||||
})
|
||||
.unwrap_or_else(|| source.rsplit('\\').next().unwrap());
|
||||
let mut result = HashMap::new();
|
||||
while let Some(method_call) = use_calls.next() {
|
||||
let source = method_call.captures[0]
|
||||
.node
|
||||
.utf8_text(code.as_bytes())
|
||||
.unwrap_or("malformed utf8")
|
||||
.trim_start_matches('\\');
|
||||
let target = method_call
|
||||
.captures
|
||||
.get(1)
|
||||
.map(|capture| {
|
||||
capture
|
||||
.node
|
||||
.utf8_text(code.as_bytes())
|
||||
.expect("invalid utf8")
|
||||
})
|
||||
.unwrap_or_else(|| source.rsplit('\\').next().unwrap());
|
||||
|
||||
(target, source)
|
||||
})
|
||||
.collect()
|
||||
if !result.contains_key(&target) {
|
||||
result.insert(target, source);
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn get_namespace<'a>(
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
use databake::Bake;
|
||||
use logging_extractor::error::Error;
|
||||
use logging_extractor::extract_dir;
|
||||
use nextcloud_appinfo::get_appinfo;
|
||||
use nextcloud_route_extractor::{app_routes, core_routes};
|
||||
use std::env::args;
|
||||
use std::fs::canonicalize;
|
||||
use std::io::stdout;
|
||||
use std::fs::{canonicalize, read_dir};
|
||||
use std::io::{stdout, Write};
|
||||
use std::path::Path;
|
||||
|
||||
fn main() -> Result<(), Error> {
|
||||
let root = args().nth(1).expect("no root provided");
|
||||
|
|
@ -13,7 +17,76 @@ fn main() -> Result<(), Error> {
|
|||
})?;
|
||||
let root = root.to_str().expect("non utf8 root path");
|
||||
|
||||
let stdout = stdout();
|
||||
let mut stdout = stdout().lock();
|
||||
|
||||
extract_dir(root, stdout, mode == "rust")
|
||||
extract_dir(root, &mut stdout, mode == "rust")?;
|
||||
if mode == "rust" {
|
||||
let _ = writeln!(&mut stdout, "pub const ROUTES: &[crate::Route] = &[\n");
|
||||
extract_routes(&mut stdout, root);
|
||||
let _ = writeln!(&mut stdout, "];");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn extract_routes<W: Write>(out: &mut W, path: &str) {
|
||||
let app = match get_appinfo(path.as_ref()) {
|
||||
Ok(info) => info.id().clone(),
|
||||
Err(nextcloud_appinfo::error::Error::InfoXmlMissing) => "core".into(),
|
||||
Err(_) => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let routes = if app == "core" {
|
||||
core_routes(&path)
|
||||
} else {
|
||||
app_routes(&path)
|
||||
}
|
||||
.unwrap();
|
||||
|
||||
for route in routes.routes {
|
||||
bake_route(out, &app, &route, false);
|
||||
}
|
||||
for route in routes.ocs {
|
||||
bake_route(out, &app, &route, true);
|
||||
}
|
||||
|
||||
if app == "core" {
|
||||
let core_apps_root = Path::new(path).join("apps");
|
||||
for core_app_dir in read_dir(core_apps_root).unwrap().flatten() {
|
||||
let app_path = core_app_dir.path();
|
||||
let app_path = app_path.to_str().unwrap();
|
||||
extract_routes(out, app_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Bake)]
|
||||
#[databake(path = crate)]
|
||||
pub struct Route<'a> {
|
||||
id: &'a str,
|
||||
url: &'a str,
|
||||
verb: &'a str,
|
||||
ocs: bool,
|
||||
}
|
||||
|
||||
fn bake_route<W: Write>(
|
||||
out: &mut W,
|
||||
app: &str,
|
||||
route: &nextcloud_route_extractor::Route,
|
||||
ocs: bool,
|
||||
) {
|
||||
let id = route.id(app);
|
||||
let url = if ocs {
|
||||
route.ocs_url(app)
|
||||
} else {
|
||||
route.frontpage_url(app)
|
||||
};
|
||||
let data = Route {
|
||||
id: id.as_str(),
|
||||
url: url.as_str(),
|
||||
verb: route.verb.as_str(),
|
||||
ocs,
|
||||
};
|
||||
let _ = writeln!(out, "\t{},", data.bake(&Default::default()));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue