Debugging from a Value converter

Hi there,
I have the following task and am investigating ways to solve it. It’s about debugging. I have a value converter that is widely used across the entire app. I want it under certain conditions, for example:

toView(value) {
  if (value?.foo === value?.bar) {
    console.info('We have a match!');
//And here I want to know which component caused the invocation of this condition.
  }
}

My aim is to get information about the place where the value converter is invoked, matching this condition.
Is that possible, and can you give me some hints on achieving such debug functionality?

I’d put a (conditional) breakpoint in it via the inspector and check the stack trace to find the call.

How do you mean “Via the inspector”?
I need something like:

...
toView(value, ...args) {
_normalizeValue(value) {
    switch (true) {
      case typeof value === 'number':
      case Number.isFinite(value):
        // call the logger service and log the wrong payload passed
        console.trace(value, 'is not a valid value');
        return { amount: value, currency: this.defaultCurrency, amountSecondary: value?.amountSecondary ?? value };
      case typeof value === 'string' && Number.isFinite(Number(value)):
        return { amount: Number(value), currency: this.defaultCurrency, amountSecondary: value?.amountSecondary ?? value };
      default:
        return { amount: value?.amount, currency: this.defaultCurrency, amountSecondary: value.amountSecondary };
    }
  }
}

I need to call let say a LoggerService in the first case and write some useful information like the name of the file or the Callee, or the class invoking the value converter in this condition.

I mean if you’re debugging and trying to find where your value converter was called, go to your browsers’ web inspector sources tab, and set a conditional breakpoint with Number.isFinite(value) == true in the source code, in the toView() method. The script will stop when it meets your condition. Then look in the stack trace to check where it was called.

Hi Esger,
Thank you for the tip. Maybe I expressed myself incorrectly. The functionality I’m looking for is invoking a logging service, which will call an endpoint and write the call stack: no browser console, no dev-tools. Testing engenders and users will browse the system, and later, I can read the logs from the server and see the place of invocation of the value converter.

2 Likes

At the moment, value converter only knows about itself, its input and output. If we want to let the value converter know more about whos calling it then likely there needs to be some signal on the value converter itself, so that during the ast evaluation we can pass the caller as 2nd parameter to the toView/fromView call. If this is necessary maybe create a Github issue to request / track this feature? It should be implemented quickly after that @vladyn

1 Like

I have created an issue here and have a plan to implement this: Feature Request: Provide Caller Context to Value Converters · Issue #2157 · aurelia/aurelia · GitHub

2 Likes

An update to this, I’ve been working on implementing this feature. I’ll have a PR up for this today.

1 Like

This is really pro-active. Thank you!

At the moment, I found a solution creating an Error inside my switch case and then finding the component based on a namespace from mt app (I have few fixed areas) and then calling the logging service:

_normalizeValue(value) {
    const amountSecondary = value?.amountSecondary ?? 0;
    const currency = this.defaultCurrency;

    switch (true) {
      case typeof value === 'number':
      case Number.isFinite(value):
        console.trace(value, 'is not a valid value');
        const callStack = new Error().stack?.split("@webpack-internal:///");
        const componentReference = callStack.filter(namespace => {
          return systemAreaNamespaces.some(name => namespace.startsWith(name) && namespace);
        });
        this.microServiceCoreLoggingService.createDummyValueConverterLog(componentReference);

        return { amount: value, currency, amountSecondary };
      case typeof value === 'string' && Number.isFinite(Number(value)):
        return { amount: Number(value), currency, amountSecondary };
      default:
        return { amount: value?.amount, currency, amountSecondary };
    }
  }

and the name spaces:

export const systemAreaNamespaces = [
  'area',
  'dashboard',
  'events',
  'libs',
  'features',
  'tasks'
];

Nice one. Hopefully the PR I am working on passes the final few pieces of feedback (it went through a couple of architecture changes) and then this is available for you shortly.

1 Like