mirror of
https://github.com/HeyPuter/puter.git
synced 2025-01-23 22:40:20 +08:00
dev: add a feature to hook tracing into context
This commit is contained in:
parent
c2b094a351
commit
08dbef7b8c
21
src/backend/src/modules/core/ContextService.js
Normal file
21
src/backend/src/modules/core/ContextService.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
const BaseService = require("../../services/BaseService");
|
||||||
|
const { Context } = require("../../util/context");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ContextService provides a way for other services to register a hook to be
|
||||||
|
* called when a context/subcontext is created.
|
||||||
|
*
|
||||||
|
* Contexts are used to provide contextual information in the execution
|
||||||
|
* context (dynamic scope). They can also be used to identify a "span";
|
||||||
|
* a span is a labelled frame of execution that can be used to track
|
||||||
|
* performance, errors, and other metrics.
|
||||||
|
*/
|
||||||
|
class ContextService extends BaseService {
|
||||||
|
register_context_hook (event, hook) {
|
||||||
|
Context.context_hooks_[event].push(hook);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
ContextService,
|
||||||
|
};
|
@ -50,6 +50,9 @@ class Core2Module extends AdvancedBase {
|
|||||||
|
|
||||||
const { ParameterService } = require("./ParameterService.js");
|
const { ParameterService } = require("./ParameterService.js");
|
||||||
services.registerService('params', ParameterService);
|
services.registerService('params', ParameterService);
|
||||||
|
|
||||||
|
const { ContextService } = require('./ContextService.js');
|
||||||
|
services.registerService('context', ContextService);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,13 @@ class Context {
|
|||||||
static USE_NAME_FALLBACK = {};
|
static USE_NAME_FALLBACK = {};
|
||||||
static next_name_ = 0;
|
static next_name_ = 0;
|
||||||
static other_next_names_ = {};
|
static other_next_names_ = {};
|
||||||
|
|
||||||
|
// Context hooks should be registered via service (ContextService.js)
|
||||||
|
static context_hooks_ = {
|
||||||
|
pre_create: [],
|
||||||
|
post_create: [],
|
||||||
|
pre_arun: [],
|
||||||
|
};
|
||||||
|
|
||||||
static contextAsyncLocalStorage = new AsyncLocalStorage();
|
static contextAsyncLocalStorage = new AsyncLocalStorage();
|
||||||
static __last_context_key = 0;
|
static __last_context_key = 0;
|
||||||
@ -59,8 +66,8 @@ class Context {
|
|||||||
static describe () {
|
static describe () {
|
||||||
return this.get().describe();
|
return this.get().describe();
|
||||||
}
|
}
|
||||||
static arun (cb) {
|
static arun (...a) {
|
||||||
return this.get().arun(cb);
|
return this.get().arun(...a);
|
||||||
}
|
}
|
||||||
static sub (values, opt_name) {
|
static sub (values, opt_name) {
|
||||||
return this.get().sub(values, opt_name);
|
return this.get().sub(values, opt_name);
|
||||||
@ -72,6 +79,14 @@ class Context {
|
|||||||
this.values_[k] = v;
|
this.values_[k] = v;
|
||||||
}
|
}
|
||||||
sub (values, opt_name) {
|
sub (values, opt_name) {
|
||||||
|
if ( typeof values === 'string' ) {
|
||||||
|
opt_name = values;
|
||||||
|
values = {};
|
||||||
|
}
|
||||||
|
const name = opt_name ?? this.name ?? this.get('name');
|
||||||
|
for ( const hook of this.constructor.context_hooks_.pre_create ) {
|
||||||
|
hook({ values, name });
|
||||||
|
}
|
||||||
return new Context(values, this, opt_name);
|
return new Context(values, this, opt_name);
|
||||||
}
|
}
|
||||||
get values () {
|
get values () {
|
||||||
@ -99,6 +114,7 @@ class Context {
|
|||||||
|
|
||||||
opt_parent = opt_parent || Context.root;
|
opt_parent = opt_parent || Context.root;
|
||||||
|
|
||||||
|
this.trace_name = opt_name ?? undefined;
|
||||||
this.name = (() => {
|
this.name = (() => {
|
||||||
if ( opt_name === this.constructor.USE_NAME_FALLBACK ) {
|
if ( opt_name === this.constructor.USE_NAME_FALLBACK ) {
|
||||||
opt_name = 'F';
|
opt_name = 'F';
|
||||||
@ -129,7 +145,34 @@ class Context {
|
|||||||
|
|
||||||
this.values_ = values;
|
this.values_ = values;
|
||||||
}
|
}
|
||||||
async arun (cb) {
|
async arun (...args) {
|
||||||
|
let cb = args.shift();
|
||||||
|
|
||||||
|
let hints = {};
|
||||||
|
if ( typeof cb === 'object' ) {
|
||||||
|
hints = cb;
|
||||||
|
cb = args.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( typeof cb === 'string' ) {
|
||||||
|
const sub_context = this.sub(cb);
|
||||||
|
return await sub_context.arun({ trace: true }, ...args);
|
||||||
|
}
|
||||||
|
|
||||||
|
const replace_callback = new_cb => {
|
||||||
|
cb = new_cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( const hook of this.constructor.context_hooks_.pre_arun ) {
|
||||||
|
hook({
|
||||||
|
hints,
|
||||||
|
name: this.name ?? this.get('name'),
|
||||||
|
trace_name: this.trace_name,
|
||||||
|
replace_callback,
|
||||||
|
callback: cb,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const als = this.constructor.contextAsyncLocalStorage;
|
const als = this.constructor.contextAsyncLocalStorage;
|
||||||
return await als.run(new Map(), async () => {
|
return await als.run(new Map(), async () => {
|
||||||
als.getStore().set('context', this);
|
als.getStore().set('context', this);
|
||||||
|
Loading…
Reference in New Issue
Block a user