Inversifyjs: Inversify-logger-middleware fails with symbol-binding

Created on 12 Sep 2016  ·  8Comments  ·  Source: inversify/InversifyJS

Behavior

The logger middleware should work correctly when using the recommended way of binding: with Symbols instead of strings. Now a TypeError is thrown: TypeError: Cannot convert a Sy mbol value to a string

Possible Solution

In src/serializers/text/request_serializer.ts the part of line 21

`Binding<${request.serviceIdentifier}>` `Binding<${request.serviceIdentifier}>`

transpiles to

"Binding<" + request.serviceIdentifier + ">"

which throws an error if serviceIdentifier is not a string! I suggest using toString()

Steps to Reproduce (for bugs)

  1. Create a Class with a Symbol binding
  2. Add the inversify-logger-middleware with the default text serializer
  3. Try to run code where you try to get an instance of the class from the kernel
bug

All 8 comments

Thanks for reporting this issue. I will fix it this evening

It would be nice to have a serviceIdentifierFormatter instead of just toString() to support all kind of serviceIdentifier types (Symbol, string and class). Otherwise it will log the whole implementation of a class in case of a class identifier

I need to check but I think it uses kernel.getServiceIdentifierAsString.

A class is a function at run-time so it should show the class name not the whole class? If is not working like that could you please share some code to reproduce the issue?

Thanks!

Here is the code to reproduce the error when using Symbol:

import 'reflect-metadata';
import { Kernel, inject, injectable } from 'inversify';
import { makeLoggerMiddleware, textSerializer } from 'inversify-logger-middleware';

const TYPES = {
  MyService: Symbol('MyService'),
  MyController: Symbol('MyController')
};

@injectable()
class MyService {
  foo() {
    return 123;
  }
}

@injectable()
class MyController {
  constructor(
      @inject(TYPES.MyService) private myService: MyService
    ) { }

    bar() {
      return this.myService.foo();
    }
}

const kernel = new Kernel();
kernel.bind<MyService>(TYPES.MyService).to(MyService).inSingletonScope();
kernel.bind<MyController>(TYPES.MyController).to(MyController).inSingletonScope();

let logger = makeLoggerMiddleware();
kernel.applyMiddleware(logger);

let myController = kernel.get<MyController>(TYPES.MyController);

This yields the following stack-trace:

<project-root>/node_modules/inversify-logger-middleware/lib
/serializers/text/request_serializer.js:16                                  
            textEntry = propertyLogger(textEntry, 2, "Binding<" + request.se
rviceIdentifier + ">", bindingIndex.toString());                            
                                                                ^           

TypeError: Cannot convert a Symbol value to a string                        
    at <project-root>/node_modules/inversify-logger-middleware/lib/serializers/text/request_serializer.js:16:65                        
    at Array.forEach (native)                                               
    at Object.serializeRequest [as default] (<project-root>/node_modules/inversify-logger-middleware/lib/serializers/text/request_serializer.js:15:26)
    at Object.textSerializer [as default] (<project-root>/node_modules/inversify-logger-middleware/lib/serializers/text/text_serializer.js:12:45)                                                                  
    at consoleRenderer (<project-root>/node_modules/inversify-logger-middleware/lib/renderers/console_renderer.js:4:37)                
    at Kernel._middleware (<project-root>/node_modules/inversify-logger-middleware/lib/index.js:53:13)                                 
    at Kernel._get (<project-root>/node_modules/inversify/lib/kernel/kernel.js:162:27)                                                 
    at Kernel.get (<project-root>/node_modules/inversify/lib/kernel/kernel.js:76:21)                                                   
    at Object.<anonymous> (<project-root>/index.js:48:27)  
    at Module._compile (module.js:541:32)                                   

And using (almost) the same code with Classes:

import 'reflect-metadata';
import { Kernel, inject, injectable } from 'inversify';
import { makeLoggerMiddleware, textSerializer } from 'inversify-logger-middleware';

@injectable()
class MyService {
  foo() {
    return 123;
  }
}

@injectable()
class MyController {
  constructor(
      @inject(MyService) private myService: MyService
    ) { }

    bar() {
      return this.myService.foo();
    }
}

const kernel = new Kernel();
kernel.bind<MyService>(MyService).to(MyService).inSingletonScope();
kernel.bind<MyController>(MyController).to(MyController).inSingletonScope();

let logger = makeLoggerMiddleware(null, (entry) => console.log(textSerializer(entry)));
kernel.applyMiddleware(logger);

let myController = kernel.get<MyController>(MyController);

gives the following not very nice output (not using the kernel.getServiceIdentifierAsString you mentioned):

SUCCESS: 5.92 ms.
    └── Request : 0
        └── serviceIdentifier : class MyController {    constructor(myService) {        this.myService = myService;    }    bar() {        return this.myService.foo();    }}
        └── bindings
            └── Binding<class MyController {
    constructor(myService) {
        this.myService = myService;
    }
    bar() {
        return this.myService.foo();
    }
}> : 0
                └── type : Instance
                └── implementationType : MyController
                └── scope : Singleton
        └── childRequests
            └── Request : 0
                └── serviceIdentifier : class MyService {    foo() {        return 123;    }}
                └── bindings
                    └── Binding<class MyService {
    foo() {
        return 123;
    }
}> : 0
                        └── type : Instance
                        └── implementationType : MyService
                        └── scope : Singleton
                └── target
                    └── serviceIdentifier : class MyService {    foo() {        return 123;    }}
                    └── name : undefined
                    └── metadata
                        └── Metadata : 0
                            └── key : inject
                            └── value : class MyService {    foo() {        return 123;    }}

Hi @andreasrueedlinger thanks for helping out I'm working on this now. Will share PR and release when I get them ready...

Your use case about classes will now generate:

SUCCESS: 0.78 ms.
    └── Request : 0
        └── serviceIdentifier : MyController
        └── bindings
            └── Binding<MyController> : 0
                └── type : Instance
                └── implementationType : MyController
                └── scope : Singleton
        └── childRequests
            └── Request : 0
                └── serviceIdentifier : MyService
                └── bindings
                    └── Binding<MyService> : 0
                        └── type : Instance
                        └── implementationType : MyService
                        └── scope : Singleton
                └── target
                    └── serviceIdentifier : MyService
                    └── name : myService
                    └── metadata
                        └── Metadata : 0
                            └── key : inject
                            └── value : MyService

Your case about symbols will generate:

SUCCESS: 1.71 ms.
    └── Request : 0
        └── serviceIdentifier : Symbol(MyController)
        └── bindings
            └── Binding<Symbol(MyController)> : 0
                └── type : Instance
                └── implementationType : MyController
                └── scope : Singleton
        └── childRequests
            └── Request : 0
                └── serviceIdentifier : Symbol(MyService)
                └── bindings
                    └── Binding<Symbol(MyService)> : 0
                        └── type : Instance
                        └── implementationType : MyService
                        └── scope : Singleton
                └── target
                    └── serviceIdentifier : Symbol(MyService)
                    └── name : myService
                    └── metadata
                        └── Metadata : 0
                            └── key : inject
                            └── value : Symbol(MyService)

This has already been implemented by inversify/inversify-logger-middleware/pull/28 and will be released with [email protected]

This should be now fixed:

screen shot 2016-09-13 at 01 04 15

Was this page helpful?
0 / 5 - 0 ratings

Related issues

inaiei picture inaiei  ·  4Comments

remojansen picture remojansen  ·  4Comments

codyjs picture codyjs  ·  3Comments

RastriginSergey picture RastriginSergey  ·  3Comments

stjepangolemac picture stjepangolemac  ·  5Comments