moleculer

Progressive microservices framework for Node.js

MIT License

Downloads
187.9K
Stars
6K
Committers
147

Bot releases are visible (Hide)

moleculer - v0.14.13

Published by icebob over 3 years ago

Changes (62 commits from 12 contributors)

  • update dependencies
  • logging if encryption middleware can't decrypt the data instead of crashing. #853
  • fix disableHeartbeatChecks option handling. #858
  • force scanning only master redis nodes for deletion. #865
  • add more info into waitForServices debug log messages. #870
  • fix EVENT packet Avro schema. #856
  • fix array & date conversion in cacher default key generator. #883
  • fix Datadog tracing exporter. #890
  • better elapsed time handling in tracing. #899
  • improve type definitions. #843, #885, #886
  • add E2E tests for CI (test all built-in transporter & serializers)
moleculer - v0.14.12

Published by icebob almost 4 years ago

Other changes

  • update dependencies
  • improved type definitions. #816 #817 #834 #840
  • support rediss:// cacher URI. #837
  • fix Event Trace exporter generated events loop. #836
  • change log level of node disconnected message. #838
  • improve the broker.waitForServices response. #843
  • fix recursive hot-reload issue on Linux OS. #848
moleculer - v0.14.11

Published by icebob about 4 years ago

New merged service lifecycle hook

Service has a new merged lifecycle hook which is called after the service schemas (including mixins) has been merged but before service is registered. It means you can manipulate the merged service schema before it's processed.

Example

// posts.service.js
module.exports = {
    name: "posts",

    settings: {},

    actions: {
        find: {
            params: {
                limit: "number"
            }
            handler(ctx) {
                // ...
            }
        }
    },

    merged(schema) {
        // Modify the service settings
        schema.settings.myProp = "myValue";
        // Modify the param validation schema in an action schema
        schema.actions.find.params.offset = "number";
    }
};

Other changes

  • add requestID tag to all action and event spans #802
  • fix bug in second level of mixins with $secureSettings #811
moleculer - v0.14.10

Published by icebob about 4 years ago

Changes

  • update dependencies
  • fix issues in index.d.ts
  • fix broadcast event sending issue when disableBalancer: true #799 (thanks for @ngraef)
moleculer - v0.14.9

Published by icebob about 4 years ago

Register method in module resolver

If you create a custom module (e.g. serializer), you can register it into the built-in modules with the register method. This method is also available in all other built-in module resolver.

Example

// SafeJsonSerializer.js
const { Serializers } = require("moleculer");

class SafeJsonSerializer {}

Serializers.register("SafeJSON", SafeJSON);

module.exports = SafeJsonSerializer;
// moleculer.config.js
require("./SafeJsonSerializer");

module.exports = {
    nodeID: "node-100",
    serializer: "SafeJSON"
    // ...
});

Changeable validation property name

You can change the params property name in validator options. It can be useful if you have a custom Validator implementation.

const broker = new ServiceBroker({
    validator: {
        type: "Fastest",
        options: {
            paramName: "myParams" // using `myParams` instead of `params`
        }
    }
});

broker.createService({
    name: "posts",
    actions: {
        create: {
            myParams: {
                title: "string"
            }
        },
        handler(ctx) { /* ... */ }
    }
});

Global tracing span tags for actions & events

Thanks for @kthompson23, you can configure the action & events tracing span tags globally. These tags will be used for all actions & events where tracing is enabled. Of course, you can overwrite them locally in the action & event schema.

Example

// moleculer.config.js
module.exports = {
    tracing: {
        enabled: true,
        exporter: 'Zipkin',
        tags: {
            action: {
                meta: ['app.id', 'user.email', 'workspace.name'],
                params: false,  // overrides default behavior of all params being adding as tags
                response: true,
            },
            event: (ctx) {
                return {
                    caller: ctx.caller,
                }
            }  
        }
    }
}

Other changes

  • fix multiple trace spans with same ID issue in case of retries.
  • update dependencies
  • add lastValue property to histogram metric type.
  • update return type of context's copy method.
  • add configuration hotReloadModules #779
  • Remove Zipkin v1 annotations and change kind to SERVER
moleculer - v0.14.8

Published by icebob over 4 years ago

Github Sponsoring is available for Moleculer 🎉

We have been approved in Github Sponsors program, so you can sponsor the Moleculer project via Github Sponsors.
If you have taxing problem with Patreon, change to Github Sponsors.

New Validator configuration

The validator has the same module configuration in broker options like other modules. It means you can configure the validation constructor options via broker options (moleculer.config.js).

Default usage:

//moleculer.config.js
module.exports = {
    nodeID: "node-100",
    validator: true // Using the default Fastest Validator
}

Using built-in validator name:

//moleculer.config.js
module.exports = {
    nodeID: "node-100",
    validator: "FastestValidator" // Using the Fastest Validator
}

Example with options:

//moleculer.config.js
module.exports = {
    nodeID: "node-100",
    validator: {
        type: "FastestValidator",
        options: {
            useNewCustomCheckerFunction: true,
            defaults: { /*...*/ },
            messages: { /*...*/ },
            aliases: { /*...*/ }
        }
    }
}

Example with custom validator

//moleculer.config.js
const BaseValidator = require("moleculer").Validators.Base;

class MyValidator extends BaseValidator {}

module.exports = {
    nodeID: "node-100",
    validator: new MyValidator()
}

New metrics

Added the following new metrics:

  • moleculer.event.received.active: Number of active event executions.
  • moleculer.event.received.error.total: Number of event execution errors.
  • moleculer.event.received.time: Execution time of events in milliseconds.
  • os.memory.total: OS used memory size.

Other changes

  • support using moleculer.config.js with export default.
  • remove some lodash methods.
  • upgrade to the latest tsd.
  • new dependencyInterval broker option. Using as default value for broker.waitForServices #761
  • fix Datadog traceID, spanID generation logic to work with latest dd-trace.
  • add error stack trace to EventLegacy trace exporter.
  • fix INFO key issue in Redis Discoverer after Redis server restarting.
moleculer - v0.14.7

Published by icebob over 4 years ago

New Discoverer module

The Discoverer is a new built-in module in Moleculer framework. It's responsible for that all Moleculer nodes can discover each other and check them with heartbeats. In previous versions, it was an integrated module inside ServiceRegistry & Transit modules. In this version, the discovery logic has been extracted to a separated built-in module. It means you can replace it to other built-in implementations or a custom one. The current discovery & heartbeat logic is moved to the Local Discoverer.

Nevertheless, this version also contains other discoverers, like Redis & etcd3 discoverers. Both of them require an external server to make them work.
One of the main advantages of the external discoverers, the node discovery & heartbeat packets don't overload the communication on the transporter. The transporter transfers only the request, response, event packets.
By the way, the external discoverers have some disadvantages, as well. These discoverers can detect lazier the new and disconnected nodes because they scan the heartbeat keys periodically on the remote Redis/etcd3 server. The period of checks depends on the heartbeatInterval broker option.

The Local Discoverer (which is the default) works like the discovery of previous versions, so if you want to keep the original logic, you'll have to do nothing.

Please note the TCP transporter uses Gossip protocol & UDP packets for discovery & heartbeats, it means it can work only with Local Discoverer.

Local Discoverer

It's the default Discoverer, it uses the transporter module to discover all other moleculer nodes. It's quick and fast but if you have too many nodes (>100), the nodes can generate a lot of heartbeat packets which can reduce the performance of request/response packets.

Example

// moleculer.config.js
module.exports = {
    registry: {
        discoverer: "Local"
    }    
}

Example with options

// moleculer.config.js
module.exports = {
    registry: {
        discoverer: {
            type: "Local",
            options: {
                // Send heartbeat in every 10 seconds
                heartbeatInterval: 10,

                // Heartbeat timeout in seconds
                heartbeatTimeout: 30,

                // Disable heartbeat checking & sending, if true
                disableHeartbeatChecks: false,

                // Disable removing offline nodes from registry, if true
                disableOfflineNodeRemoving: false,

                // Remove offline nodes after 10 minutes
                cleanOfflineNodesTimeout: 10 * 60
            }
        }
    }    
}

Redis Discoverer

This is an experimental module. Do not use it in production yet!

This Discoverer uses a Redis server to discover Moleculer nodes. The heartbeat & discovery packets are stored in Redis keys. Thanks to Redis key expiration, if a node crashed or disconnected unexpectedly, the Redis will remove its heartbeat keys from the server and other nodes can detect it.

Example to connect local Redis server

// moleculer.config.js
module.exports = {
    registry: {
        discoverer: "Redis"
    }    
}

Example to connect remote Redis server

// moleculer.config.js
module.exports = {
    registry: {
        discoverer: "redis://redis-server:6379"
    }    
}

Example with options

// moleculer.config.js
module.exports = {
    registry: {
        discoverer: {
            type: "Redis",
            options: {
                redis: {
                    // Redis connection options.
                    // More info: https://github.com/luin/ioredis#connect-to-redis
                    port: 6379,
                    host: "redis-server",
                    password: "123456",
                    db: 3
                }

                // Serializer
                serializer: "JSON",

                // Full heartbeat checks. It generates more network traffic
                // 10 means every 10 cycle.
                fullCheck: 10,

                // Key scanning size
                scanLength: 100,

                // Monitoring Redis commands
                monitor: true,
                
                // --- COMMON DISCOVERER OPTIONS ---

                // Send heartbeat in every 10 seconds
                heartbeatInterval: 10,

                // Heartbeat timeout in seconds
                heartbeatTimeout: 30,

                // Disable heartbeat checking & sending, if true
                disableHeartbeatChecks: false,

                // Disable removing offline nodes from registry, if true
                disableOfflineNodeRemoving: false,

                // Remove offline nodes after 10 minutes
                cleanOfflineNodesTimeout: 10 * 60
            }
        }
    }    
}

To be able to use this Discoverer, install the ioredis module with the npm install ioredis --save command.

Tip: To further network traffic reduction, you can use MsgPack/Notepack serializers instead of JSON.

Etcd3 Discoverer

This is an experimental module. Do not use it in production yet!

This Discoverer uses an etcd3 server to discover Moleculer nodes. The heartbeat & discovery packets are stored in the server. Thanks to etcd3 lease solution, if a node crashed or disconnected unexpectedly, the etcd3 will remove its heartbeat keys from the server and other nodes can detect it.

Example to connect local etcd3 server

// moleculer.config.js
module.exports = {
    registry: {
        discoverer: "Etcd3"
    }    
}

Example to connect remote etcd3 server

// moleculer.config.js
module.exports = {
    registry: {
        discoverer: "etcd3://etcd-server:2379"
    }    
}

Example with options

// moleculer.config.js
module.exports = {
    registry: {
        discoverer: {
            type: "Etcd3",
            options: {
                etcd: {
                    // etcd3 connection options.
                    // More info: https://mixer.github.io/etcd3/interfaces/options_.ioptions.html
                    hosts: "etcd-server:2379",
                    auth: "12345678"
                }

                // Serializer
                serializer: "JSON",

                // Full heartbeat checks. It generates more network traffic
                // 10 means every 10 cycle.
                fullCheck: 10,
                
                // --- COMMON DISCOVERER OPTIONS ---

                // Send heartbeat in every 10 seconds
                heartbeatInterval: 10,

                // Heartbeat timeout in seconds
                heartbeatTimeout: 30,

                // Disable heartbeat checking & sending, if true
                disableHeartbeatChecks: false,

                // Disable removing offline nodes from registry, if true
                disableOfflineNodeRemoving: false,

                // Remove offline nodes after 10 minutes
                cleanOfflineNodesTimeout: 10 * 60
            }
        }
    }    
}

To be able to use this Discoverer, install the etcd3 module with the npm install etcd3--save command.

Tip: To further network traffic reduction, you can use MsgPack/Notepack serializers instead of JSON.

Custom Discoverer

You can create your custom Discoverer. We recommend to copy the source of Redis Discoverer and implement the necessary methods.

Other changes

  • fixed multiple heartbeat sending issue at transporter reconnecting.
  • the heartbeatInterval default value has been changed to 10 seconds.
  • the heartbeatTimeout default value has been changed to 30 seconds.
  • the heartbeat check logics use process uptime instead of timestamps in order to avoid issues with time synchronization or daylight saving.
  • Notepack serializer initialization issue fixed. It caused problem when Redis cacher uses Notepack serializer.
  • new removeFromArray function in Utils.
  • mcall method definition fixed in Typescript definition.
  • dependencies updated.
moleculer - v0.14.6

Published by icebob over 4 years ago

New NewRelic zipkin tracing exporter

Thanks for @jalerg, there is a NewRelic tracing exporter. PR #713

// moleculer.config.js
{
    tracing: {
        enabled: true,
        events: true,
        exporter: [
            {
                type: 'NewRelic',
                options: {
                    // NewRelic Insert Key
                    insertKey: process.env.NEW_RELIC_INSERT_KEY,
                    // Sending time interval in seconds.
                    interval: 5,
                    // Additional payload options.
                    payloadOptions: {
                        // Set `debug` property in payload.
                        debug: false,
                        // Set `shared` property in payload.
                        shared: false,
                    },
                    // Default tags. They will be added into all span tags.
                    defaultTags: null,
                },
            },
        ],
    },    
}

Other changes

  • fix stream chunking issue. PR #712
  • fix INFO packet sending issue after reconnecting
  • safely handling disconnected state for transporters (heartbeat queuing issue). PR #715
  • fix orphan response issue in case of streaming with disabled balancer. #709
  • update dependencies, audit fix
moleculer - v0.14.5

Published by icebob over 4 years ago

Wrapping service methods with middlewares

New localMethod hook in middlewares which wraps the service methods.

Example

// my.middleware.js
module.exports = {
    name: "MyMiddleware",

    localMethod(next, method) {
        return (...args) => {
            console.log(`The '${method.name}' method is called in '${method.service.fullName}' service.`, args);
            return handler(...args);
        }
    }
}

Schema for service methods

Similar for action schema, you can define service methods with schema. It can be useful when middleware wraps service methods.

Example for new method schema

// posts.service.js
module.exports = {
    name: "posts",

    methods: {
        list: {
            async handler(count) {
                // Do something
                return posts;
            }
        }
    }
};

Changes

  • add chunk limit for streams in message transporting. #683
  • add baseUrl option to Datadog metric reporter. #694
  • fix open handles in unit tests. #695
  • update d.ts #699 #700 #703
moleculer - v0.14.4

Published by icebob over 4 years ago

Changes

  • add stop method to tracing exporters. Fixes #689
  • fix EventLegacy tracing exporter. Fixes #676
  • the defaultTags property in tracer options can be a Function, as well.
moleculer - v0.14.3

Published by icebob over 4 years ago

Changes

  • fix issue in AMQP 1.0 transporter
moleculer - v0.14.2

Published by icebob over 4 years ago

Support custom loggers

If you have your custom logger you should wrap it into a Logger class and implement the getLogHandler method.

Using a custom logger

// moleculer.config.js
 const BaseLogger = require("moleculer").Loggers.Base;

class MyLogger extends BaseLogger {
    getLogHandler(bindings) {
        return (type, args) => console[type](`[MYLOG-${bindings.mod}]`, ...args);
    }
}

module.exports = {
    logger: new MyLogger()
};
moleculer - v0.14.1

Published by icebob over 4 years ago

Changes

  • fix bluebird import issue #674
moleculer - v0.14.0

Published by icebob over 4 years ago

🎉 First 0.14 stable version. Full changelog: https://github.com/moleculerjs/moleculer/blob/master/CHANGELOG.md#0140-2020-02-12

Migration guide: https://github.com/moleculerjs/moleculer/blob/master/docs/MIGRATION_GUIDE_0.14.md

Changes since 0.14.0-rc2

AMQP 1.0 transporter

Thanks for @vladir95, AMQP 1.0 transporter is available.

Please note, it is an experimental transporter. Do not use it in production yet!

// moleculer.config.js
module.exports = {
    transporter: "amqp10://activemq-server:5672"
};

To use this transporter install the rhea-promise module with npm install rhea-promise --save command.

Transporter options

Options can be passed to rhea.connection.open() method, the topics, the queues, and the messages themselves.

Connect to 'amqp10://guest:guest@localhost:5672'

// moleculer.config.js
module.exports = {
    transporter: "AMQP10"
};

Connect to a remote server

// moleculer.config.js
module.exports = {
    transporter: "amqp10://activemq-server:5672"
};

Connect to a remote server with options & credentials

// moleculer.config.js
module.exports = {
    transporter: {
        url: "amqp10://user:pass@activemq-server:5672",
        eventTimeToLive: 5000,
        heartbeatTimeToLive: 5000,
        connectionOptions: { // rhea connection options https://github.com/amqp/rhea#connectoptions, example:
            ca: "", // (if using tls)
            servername: "", // (if using tls)
            key: "", // (if using tls with client auth)
            cert: "" // (if using tls with client auth)
        },
        queueOptions: {}, // rhea queue options https://github.com/amqp/rhea#open_receiveraddressoptions
        topicOptions: {}, // rhea queue options https://github.com/amqp/rhea#open_receiveraddressoptions
        messageOptions: {}, // rhea message specific options https://github.com/amqp/rhea#message
        topicPrefix: "topic://", // RabbitMq uses '/topic/' instead, 'topic://' is more common
        prefetch: 1
    }
};

Redis Cluster feature in Redis transporter

Thanks for AAfraitane, use can connect to a Redis Cluster with the Redis transporter.

Connect to Redis cluster

// moleculer.config.js
module.exports = {
    transporter: {
        type: "Redis",
        options: {
            cluster: {
                nodes: [
                    { host: "localhost", port: 6379 },
                    { host: "localhost", port: 6378 }
                ]
            }
        }
    }
};
moleculer - v0.13.13

Published by icebob over 4 years ago

AMQP 1.0 transporter

Thanks for @vladir95, AMQP 1.0 transporter is available.

Please note, it is an experimental transporter. Do not use it in production yet!

// moleculer.config.js
module.exports = {
    transporter: "amqp10://activemq-server:5672"
};

To use this transporter install the rhea-promise module with npm install rhea-promise --save command.

Transporter options

Options can be passed to rhea.connection.open() method, the topics, the queues, and the messages themselves.

Connect to 'amqp10://guest:guest@localhost:5672'

// moleculer.config.js
module.exports = {
    transporter: "AMQP10"
};

Connect to a remote server

// moleculer.config.js
module.exports = {
    transporter: "amqp10://activemq-server:5672"
};

Connect to a remote server with options & credentials

// moleculer.config.js
module.exports = {
    transporter: {
        url: "amqp10://user:pass@activemq-server:5672",
        eventTimeToLive: 5000,
        heartbeatTimeToLive: 5000,
        connectionOptions: { // rhea connection options https://github.com/amqp/rhea#connectoptions, example:
            ca: "", // (if using tls)
            servername: "", // (if using tls)
            key: "", // (if using tls with client auth)
            cert: "" // (if using tls with client auth)
        },
        queueOptions: {}, // rhea queue options https://github.com/amqp/rhea#open_receiveraddressoptions
        topicOptions: {}, // rhea queue options https://github.com/amqp/rhea#open_receiveraddressoptions
        messageOptions: {}, // rhea message specific options https://github.com/amqp/rhea#message
        topicPrefix: "topic://", // RabbitMq uses '/topic/' instead, 'topic://' is more common
        prefetch: 1
    }
};

Redis Cluster feature in Redis transporter

Thanks for AAfraitane, use can connect to a Redis Cluster with the Redis transporter.

Connect to Redis cluster

// moleculer.config.js
module.exports = {
    transporter: {
        type: "Redis",
        options: {
            cluster: {
                nodes: [
                    { host: "localhost", port: 6379 },
                    { host: "localhost", port: 6378 }
                ]
            }
        }
    }
};
moleculer - v0.14.0-beta3

Published by icebob over 4 years ago

Changes

  • added ctx.locals
  • update dependencies
  • Fixed #570
moleculer - v0.14.0-beta5

Published by icebob over 4 years ago

Changes

  • Fixed #576, #593, #598, #599
  • Added rating to metrics
  • Added Throttle & Debounce middlewares
  • Added tracking support for events.
moleculer - v0.14.0-beta4

Published by icebob over 4 years ago

Logger settings changed

The whole logging function has been rewritten in this version. It means, it has a lot of new features, but the configuration of loggers has contains breaking changes. You can't use some old custom logger configuration form. The new configuration same as the other Moleculer module configurations. This new version supports all famous loggers like Pino, Winston, Bunyan, Debug & Log4js.

If you are using the built-in default console logger, this breaking change doesn't affect you.

The logFormatter and logObjectPrinter broker options has been removed and moved into the Console and File logger options.

Not changed usable configurations

// moleculer.config.js
module.exports = {
    // Enable console logger
    logger: true,

    // Disable all loggers
    logger: false
};

You CANNOT use these legacy configurations

// moleculer.config.js
module.exports = {
    // DON'T use a custom create function, like
    logger: bindings => pino.child(bindings),

    // DON'T use a custom logger, like
    logger: {
        error: () => { ... },
        warn: () => { ... },
        info: () => { ... },
        debug: () => { ... }
    }
};

Console logger

This logger prints all log messags to the console. It supports several built-in formatters or you can use your custom formatter, as well.

Shorthand configuration with default options

// moleculer.config.js
module.exports = {
    logger: "Console",
};

Full configuration

// moleculer.config.js
module.exports = {
    logger: {
        type: "Console",
        options: {
            // Logging level
            level: "info",
            // Using colors on the output
            colors: true,
            // Print module names with different colors (like docker-compose for containers)
            moduleColors: false,
            // Line formatter. It can be "json", "short", "simple", "full", a `Function` or a template string like "{timestamp} {level} {nodeID}/{mod}: {msg}"
            formatter: "full",
            // Custom object printer. If not defined, it uses the `util.inspect` method.
            objectPrinter: null,
            // Auto-padding the module name in order to messages begin at the same column.
            autoPadding: false
        }
    }
};

File logger

This logger saves all log messages to file(s). It supports JSON & formatted text files or you can use your custom formatter, as well.

Shorthand configuration with default options

// moleculer.config.js
module.exports = {
    logger: "File",
};

It will save the log messages to the logs folder in the current directory with moleculer-{date}.log filename.

Full configuration

// moleculer.config.js
module.exports = {
    logger: {
        type: "File",
        options: {
            // Logging level
            level: "info",
            // Folder path to save files. You can use {nodeID} & {namespace} variables.
            folder: "./logs",
            // Filename template. You can use {date}, {nodeID} & {namespace} variables.
            filename: "moleculer-{date}.log",
            // Line formatter. It can be "json", "short", "simple", "full", a `Function` or a template string like "{timestamp} {level} {nodeID}/{mod}: {msg}"
            formatter: "json",
            // Custom object printer. If not defined, it uses the `util.inspect` method.
            objectPrinter: null,
            // End of line. Default values comes from the OS settings.
            eol: "\n",
            // File appending interval in milliseconds.
            interval: 1 * 1000
        }
    }
};

Pino logger

This logger uses the Pino logger.

Shorthand configuration with default options

// moleculer.config.js
module.exports = {
    logger: "Pino",
};

Full configuration

// moleculer.config.js
module.exports = {
    logger: {
        type: "Pino",
        options: {
            // Logging level
            level: "info",

            pino: {
                // More info: http://getpino.io/#/docs/api?id=options-object
                options: null,

                // More info: http://getpino.io/#/docs/api?id=destination-sonicboom-writablestream-string
                destination: "/logs/moleculer.log",
            }
        }
    }
};

To use this logger please install the pino module with npm install pino --save command.

Bunyan logger

This logger uses the Bunyan logger.

Shorthand configuration with default options

// moleculer.config.js
module.exports = {
    logger: "Bunyan",
};

Full configuration

// moleculer.config.js
module.exports = {
    logger: {
        type: "Bunyan",
        options: {
            // Logging level
            level: "info",

            bunyan: {
                // More settings: https://github.com/trentm/node-bunyan#constructor-api
                name: "moleculer"
            }
        }
    }
};

To use this logger please install the bunyan module with npm install bunyan --save command.

Winston logger

This logger uses the Winston logger.

Shorthand configuration with default options

// moleculer.config.js
module.exports = {
    logger: "Winston",
};

Full configuration

// moleculer.config.js
const winston = require("winston");

module.exports = {
    logger: {
        type: "Winston",
        options: {
            // Logging level
            level: "info",

            winston: {
                // More settings: https://github.com/winstonjs/winston#creating-your-own-logger
                transports: [
                    new winston.transports.Console(),
                    new winston.transports.File({ filename: "/logs/moleculer.log" })
                ]
            }
        }
    }
};

To use this logger please install the winston module with npm install winston --save command.

debug logger

This logger uses the debug logger.
To see messages you have to set the DEBUG environment variable to export DEBUG=moleculer:*.

Shorthand configuration with default options

// moleculer.config.js
module.exports = {
    logger: "Debug",
};

Full configuration

// moleculer.config.js
module.exports = {
    logger: {
        type: "Debug",
        options: {
            // Logging level
            level: "info",
        }
    }
};

To use this logger please install the debug module with npm install debug --save command.

Log4js logger

This logger uses the Log4js logger.

Shorthand configuration with default options

// moleculer.config.js
module.exports = {
    logger: "Log4js",
};

Full configuration

// moleculer.config.js
module.exports = {
    logger: {
        type: "Log4js",
        options: {
            // Logging level
            level: "info",
            
            log4js: {
                // More info: https://github.com/log4js-node/log4js-node#usage
                appenders: {
                    app: { type: "file", filename: "/logs/moleculer.log" }
                },
                categories: {
                    default: { appenders: [ "app" ], level: "debug" }
                }
            }
        }
    }
};

To use this logger please install the log4js module with npm install log4js --save command.

Datadog logger

This logger uploads log messages to the Datadog server.

Please note, this logger doesn't print any messages to the console, just collects & uploads. Use it beside another logger which also prints the messages.

Shorthand configuration with default options

// moleculer.config.js
module.exports = {
    logger: "Datadog",
};

Full configuration

// moleculer.config.js
module.exports = {
    logger: {
        type: "Datadog",
        options: {
            // Logging level
            level: "info",

            // Datadog server endpoint. https://docs.datadoghq.com/api/?lang=bash#send-logs-over-http
            url: "https://http-intake.logs.datadoghq.com/v1/input/",
            // Datadog API key
            apiKey: process.env.DATADOG_API_KEY,
            // Datadog source variable
            ddSource: "moleculer",
            // Datadog env variable
            env: undefined,
            // Datadog hostname variable
            hostname: os.hostname(),
            // Custom object printer function for `Object` & `Ä„rray`
            objectPrinter: null,
            // Data uploading interval
            interval: 10 * 1000
        }
    }
};

Multiple loggers

This new logger configuration admits to use multiple loggers even from the same logger type and different logging levels.

Define multiple loggers with different logging levels

This configuration demonstrates how you can define a Console logger, a File logger to save all log messages in formatted text file and another File logger to save only error messages in JSON format.

// moleculer.config.js
module.exports = {
    logger: [
        {
            type: "Console",
            options: {
                level: "info",
            }
        },
        {            
            type: "File",
            options: {
                level: "info",
                folder: "/logs/moleculer",
                filename: "all-{date}.log",
                formatter: "{timestamp} {level} {nodeID}/{mod}: {msg}"
            }
        },
        {
            type: "File",
            options: {
                level: "error",
                folder: "/logs/moleculer",
                filename: "errors-{date}.json",
                formatter: "json"
            }
        }
    ]   
};

Using different loggers for different modules

This configuration demonstrates how you can define loggers for certain modules.

// moleculer.config.js
module.exports = {
    logger: [
        // Shorthand `Console` logger configuration
        "Console",
        {            
            // This logger saves messages from all modules except "greeter" service.
            type: "File",
            options: {
                level: {
                    "GREETER": false,
                    "**": "info"
                },
                filename: "moleculer-{date}.log"
            }
        },
        {
            // This logger saves messages from only "greeter" service.
            type: "File",
            options: {
                level: {
                    "GREETER": "debug",
                    "**": false
                },
                filename: "greeter-{date}.log"
            }
        }
    ],

    logLevel: "info" // global log level. All loggers inherits it. 
};

Logging level setting.

To configure logging levels, you can use the well-known logLevel broker option which can be a String or an Object. But it is possible to overwrite it in all logger options with the level property.

Complex logging level configuration

// moleculer.config.js
module.exports = {
    logger: [
        // The console logger will use the `logLevel` global setting.
        "Console",
        {            
            type: "File",
            options: {
                // Overwrite the global setting.
                level: {
                    "GREETER": false,
                    "**": "warn"
                }
            }
        }
    ],

    logLevel: {
        "TRACING": "trace",
        "TRANS*": "warn",
        "GREETER": "debug",
        "**": "info",
    }
};

Other Changes

  • change chalk to kleur
  • Fixed #580 (hot-reload with Runner)
  • Added timeout option to action schema.
  • Protobuf syntax with proto3
  • Using configurable serializer in Redis cacher.
  • Bulkhead for event handlers.
moleculer - v0.14.0-rc2

Published by icebob over 4 years ago

Changes

  • fix action hooks merging issue
moleculer - v0.14.0-rc1

Published by icebob over 4 years ago

Minimum Node version is 10 (BREAKING)

The Node version 8 LTS lifecycle has been ended on December 31, 2019, so the minimum required Node version is 10.

Bluebird dropped (BREAKING)

The Bluebird Promise library has been dropped from the project because as of Node 10 the native Promise implementation is faster (2x) than Bluebird.

Nonetheless, you can use your desired Promise library, just set the Promise broker options.

Using Bluebird

const BluebirdPromise = require("bluebird");

// moleculer.config.js
module.exports = {
    Promise: BluebirdPromise
};

Please note, the given Promise library will be polyfilled with delay, method, timeout and mapSeries methods (which are used inside Moleculer core modules).

Better service event handler testing

Service class has a new emitLocalEventHandler method in order to call a service event handler directly. It can be useful in Unit Tests because you don't need to emit an event with broker.emit.

Example

// posts.service.js
module.exports = {
    name: "posts",

    events: {
        async "user.created"(ctx) {
            this.myMethod(ctx.params);
        }
    }
};
// posts.service.spec.js
describe("Test events", () => {
    const broker = new ServiceBroker({ logger: false });
    const svc = broker.createService(PostService);

    beforeAll(() => broker.start());
    afterAll(() => broker.stop());

    describe("Test 'user.created' event", () => {
        beforeAll(() => svc.myMethod = jest.fn());
        afterAll(() => svc.myMethod.mockRestore());

        it("should call the event handler", async () => {
            await svc.emitLocalEventHandler("branch.closed", { a: 5 });

            expect(svc.myMethod).toBeCalledTimes(1);
            expect(svc.myMethod).toBeCalledWith({ a: 5 });
        });
    });
});

Stream objectMode support

Thanks for @artur-krueger, the request & response streams support objectMode, as well. You can also send Javascript objects via streams.

Example

Other changes

  • In metrics, the defaultBuckets value has been changed to milliseconds.
  • add caller label for EVENT_RECEIVED_TOTAL metric.
  • the heartbeat logic can be disabled by heartbeatInterval: 0 broker option.
  • remove the new currentContext property in Service & ServiceBroker.
  • in Service instances the original schema (before applying mixins) is available via this.originalSchema.