UNPKG

@stoplight/moleculer

Version:

Fast & powerful microservices framework for Node.JS

1,438 lines (1,200 loc) 202 kB
<a name="Unreleased"></a> # [Unreleased](https://github.com/moleculerjs/moleculer/compare/v0.14.18...master) -------------------------------------------------- <a name="0.14.18"></a> # [0.14.18](https://github.com/moleculerjs/moleculer/compare/v0.14.17...v0.14.18) (2021-10-20) _20 commits from 7 contributors._ ## Changes - update dependencies. - expose Cacher and Validator middlewares. [#1012](https://github.com/moleculerjs/moleculer/pull/1012) - update d.ts file. [#1013](https://github.com/moleculerjs/moleculer/pull/1013) - parse user & password from NATS server urls. [#1021](https://github.com/moleculerjs/moleculer/pull/1021) -------------------------------------------------- <a name="0.14.17"></a> # [0.14.17](https://github.com/moleculerjs/moleculer/compare/v0.14.16...v0.14.17) (2021-09-13) _61 commits from 10 contributors._ ## Changes - reformat codebase with Prettier. - fix binding issue in Pino logger. [#974](https://github.com/moleculerjs/moleculer/pull/974) - update d.ts file. [#980](https://github.com/moleculerjs/moleculer/pull/980) [#970](https://github.com/moleculerjs/moleculer/pull/970) - transit message handler promises are resolved. [#984](https://github.com/moleculerjs/moleculer/pull/984) - fix cacher issue if cacher is not connected. [#987](https://github.com/moleculerjs/moleculer/pull/987) - fix Jest open handlers issue. [#989](https://github.com/moleculerjs/moleculer/pull/989) - fix cacher cloning issue. [#990](https://github.com/moleculerjs/moleculer/pull/990) - add custom headers option to Zipkin trace exporter. [#993](https://github.com/moleculerjs/moleculer/pull/993) - fix `heartbeatTimeout` option in BaseDiscoverer. [#985](https://github.com/moleculerjs/moleculer/pull/985) - add cacher `keygen` option action definition. [#1004](https://github.com/moleculerjs/moleculer/pull/1004) - update dependencies -------------------------------------------------- <a name="0.14.16"></a> # [0.14.16](https://github.com/moleculerjs/moleculer/compare/v0.14.15...v0.14.16) (2021-07-21) _11 commits from 4 contributors._ ## Changes - fix `nats-streaming` version in peerDependencies. - RedisCacher `pingInterval` option. [#961](https://github.com/moleculerjs/moleculer/pull/961) - Update NATS transporter messages to debug. [#963](https://github.com/moleculerjs/moleculer/pull/963) - update d.ts file. [#964](https://github.com/moleculerjs/moleculer/pull/964) [#966](https://github.com/moleculerjs/moleculer/pull/966) - update dependencies -------------------------------------------------- <a name="0.14.15"></a> # [0.14.15](https://github.com/moleculerjs/moleculer/compare/v0.14.14...v0.14.15) (2021-07-10) _15 commits from 5 contributors._ ## Changes - fix `nats` version in peerDependencies. - convert `url` to `servers` in nats@2. [#954](https://github.com/moleculerjs/moleculer/pull/954) - add typing for `mcall` `settled` option. [#957](https://github.com/moleculerjs/moleculer/pull/957) - revert TS `ThisType` issue in 0.14.14. [#958](https://github.com/moleculerjs/moleculer/pull/958) - update dependencies - add `useTag259ForMaps: false` default option for CBOR serializer to keep the compatibility. -------------------------------------------------- <a name="0.14.14"></a> # [0.14.14](https://github.com/moleculerjs/moleculer/compare/v0.14.13...v0.14.14) (2021-06-27) _105 commits from 11 contributors._ ## New CBOR serializer [#905](https://github.com/moleculerjs/moleculer/pull/905) CBOR ([cbor-x](https://github.com/kriszyp/cbor-x)) is a new serializer but faster than any other serializers. **Example** ```js // moleculer.config.js module.exports = { logger: true, serializer: "CBOR" }; ``` **Benchmark** ``` Suite: Serialize packet with 10bytes √ JSON 509,217 rps √ Avro 308,711 rps √ MsgPack 79,932 rps √ ProtoBuf 435,183 rps √ Thrift 93,324 rps √ Notepack 530,121 rps √ CBOR 1,016,135 rps JSON (#) 0% (509,217 rps) (avg: 1μs) Avro -39.38% (308,711 rps) (avg: 3μs) MsgPack -84.3% (79,932 rps) (avg: 12μs) ProtoBuf -14.54% (435,183 rps) (avg: 2μs) Thrift -81.67% (93,324 rps) (avg: 10μs) Notepack +4.11% (530,121 rps) (avg: 1μs) CBOR +99.55% (1,016,135 rps) (avg: 984ns) ``` ## `settled` option in `broker.mcall` The `broker.mcall` method has a new `settled` option to receive all Promise results. Without this option, if you make a multi-call and one call is rejected, the response will be a rejected `Promise` and you don't know how many (and which) calls were rejected. If `settled: true`, the method returns a resolved `Promise` in any case and the response contains the statuses and responses of all calls. **Example** ```js const res = await broker.mcall([ { action: "posts.find", params: { limit: 2, offset: 0 }, { action: "users.find", params: { limit: 2, sort: "username" } }, { action: "service.notfound", params: { notfound: 1 } } ], { settled: true }); console.log(res); ``` The `res` will be something similar to ```js [ { status: "fulfilled", value: [/*... response of `posts.find`...*/] }, { status: "fulfilled", value: [/*... response of `users.find`...*/] }, { status: "rejected", reason: {/*... Rejected response/Error`...*/} } ] ``` ## New `MOLECULER_CONFIG` environment variable in Runner In the Moleculer Runner, you can configure the configuration filename and path with the `MOLECULER_CONFIG` environment variable. It means, no need to specify the config file with `--config` argument. ## Supporting `nats@2.x.x` in NATS transporter The new nats `2.x.x` version has a new breaking API which has locked the NATS transporter for `nats@1.x.x` library. As of this release, the NATS transporter supports both major versions of the `nats` library. _The transporter automatically detects the version of the library and uses the correct API._ ### Async custom validator functions and `ctx` as metadata Since `fastest-validator@1.11.0`, the FastestValidator supports async custom validators and you can [pass metadata for custom validator functions](https://github.com/icebob/fastest-validator/blob/master/CHANGELOG.md#meta-information-for-custom-validators). In Moleculer, the `FastestValidator` passes the `ctx` as metadata. It means you can access to the current context, service, broker and you can make async calls (e.g calling another service) in custom checker functions. **Example** ```js // posts.service.js module.exports = { name: "posts", actions: { params: { $$async: true, owner: { type: "string", custom: async (value, errors, schema, name, parent, context) => { const ctx = context.meta; const res = await ctx.call("users.isValid", { id: value }); if (res !== true) errors.push({ type: "invalidOwner", field: "owner", actual: value }); return value; } }, }, /* ... */ } } ``` ## Changes - fix node crash in encryption mode with TCP transporter. [#849](https://github.com/moleculerjs/moleculer/pull/849) - expose `Utils` in typescript definition. [#909](https://github.com/moleculerjs/moleculer/pull/909) - other d.ts improvements. [#920](https://github.com/moleculerjs/moleculer/pull/920), [#922](https://github.com/moleculerjs/moleculer/pull/922), [#934](https://github.com/moleculerjs/moleculer/pull/934), [#950](https://github.com/moleculerjs/moleculer/pull/950) - fix etcd3 discoverer lease-loss issue [#922](https://github.com/moleculerjs/moleculer/pull/922) - catch errors in Compression and Encryption middlewares. [#850](https://github.com/moleculerjs/moleculer/pull/850) - using optional peer dependencies. [#911](https://github.com/moleculerjs/moleculer/pull/911) - add relevant packet to to serialization and deserialization calls. [#932](https://github.com/moleculerjs/moleculer/pull/932) - fix disabled balancer issue with external discoverer. [#933](https://github.com/moleculerjs/moleculer/pull/933) -------------------------------------------------- <a name="0.14.13"></a> # [0.14.13](https://github.com/moleculerjs/moleculer/compare/v0.14.12...v0.14.13) (2021-04-09) _62 commits from 12 contributors._ ## Changes - update dependencies - logging if encryption middleware can't decrypt the data instead of crashing. [#853](https://github.com/moleculerjs/moleculer/pull/853) - fix `disableHeartbeatChecks` option handling. [#858](https://github.com/moleculerjs/moleculer/pull/858) - force scanning only master redis nodes for deletion. [#865](https://github.com/moleculerjs/moleculer/pull/865) - add more info into `waitForServices` debug log messages. [#870](https://github.com/moleculerjs/moleculer/pull/870) - fix `EVENT` packet Avro schema. [#856](https://github.com/moleculerjs/moleculer/issues/856) - fix array & date conversion in cacher default key generator. [#883](https://github.com/moleculerjs/moleculer/issues/883) - fix Datadog tracing exporter. [#890](https://github.com/moleculerjs/moleculer/issues/890) - better elapsed time handling in tracing. [#899](https://github.com/moleculerjs/moleculer/issues/899) - improve type definitions. [#843](https://github.com/moleculerjs/moleculer/pull/843), [#885](https://github.com/moleculerjs/moleculer/pull/885), [#886](https://github.com/moleculerjs/moleculer/pull/886) - add E2E tests for CI (test all built-in transporter & serializers) -------------------------------------------------- <a name="0.14.12"></a> # [0.14.12](https://github.com/moleculerjs/moleculer/compare/v0.14.11...v0.14.12) (2021-01-03) ## Other changes - update dependencies - improved type definitions. [#816](https://github.com/moleculerjs/moleculer/pull/816) [#817](https://github.com/moleculerjs/moleculer/pull/817) [#834](https://github.com/moleculerjs/moleculer/pull/834) [#840](https://github.com/moleculerjs/moleculer/pull/840) - support `rediss://` cacher URI. [#837](https://github.com/moleculerjs/moleculer/pull/837) - fix Event Trace exporter generated events loop. [#836](https://github.com/moleculerjs/moleculer/pull/836) - change log level of node disconnected message. [#838](https://github.com/moleculerjs/moleculer/pull/838) - improve the `broker.waitForServices` response. [#843](https://github.com/moleculerjs/moleculer/pull/843) - fix recursive hot-reload issue on Linux OS. [#848](https://github.com/moleculerjs/moleculer/pull/848) -------------------------------------------------- <a name="0.14.11"></a> # [0.14.11](https://github.com/moleculerjs/moleculer/compare/v0.14.10...v0.14.11) (2020-09-27) ## 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** ```js // 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](https://github.com/moleculerjs/moleculer/pull/802) - fix bug in second level of mixins with $secureSettings [#811](https://github.com/moleculerjs/moleculer/pull/811) -------------------------------------------------- <a name="0.14.10"></a> # [0.14.10](https://github.com/moleculerjs/moleculer/compare/v0.14.9...v0.14.10) (2020-08-23) ## Changes - update dependencies - fix issues in index.d.ts - fix broadcast event sending issue when `disableBalancer: true` [#799](https://github.com/moleculerjs/moleculer/pull/799) (thanks for [ngraef](https://github.com/ngraef)) -------------------------------------------------- <a name="0.14.9"></a> # [0.14.9](https://github.com/moleculerjs/moleculer/compare/v0.14.8...v0.14.9) (2020-08-06) ## 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** ```js // SafeJsonSerializer.js const { Serializers } = require("moleculer"); class SafeJsonSerializer {} Serializers.register("SafeJSON", SafeJSON); module.exports = SafeJsonSerializer; ``` ```js // 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. ```js 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](https://github.com/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** ```js // 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](https://github.com/moleculerjs/moleculer/pull/779) - Remove Zipkin v1 annotations and change kind to SERVER -------------------------------------------------- <a name="0.14.8"></a> # [0.14.8](https://github.com/moleculerjs/moleculer/compare/v0.14.7...v0.14.8) (2020-06-27) ## Github Sponsoring is available for Moleculer :tada: We have been approved in Github Sponsors program, so you can sponsor the Moleculer project via [Github Sponsors](https://github.com/sponsors/moleculerjs). _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:** ```js //moleculer.config.js module.exports = { nodeID: "node-100", validator: true // Using the default Fastest Validator } ``` **Using built-in validator name:** ```js //moleculer.config.js module.exports = { nodeID: "node-100", validator: "FastestValidator" // Using the Fastest Validator } ``` **Example with options:** ```js //moleculer.config.js module.exports = { nodeID: "node-100", validator: { type: "FastestValidator", options: { useNewCustomCheckerFunction: true, defaults: { /*...*/ }, messages: { /*...*/ }, aliases: { /*...*/ } } } } ``` **Example with custom validator** ```js //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](https://github.com/moleculerjs/moleculer/pull/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. -------------------------------------------------- <a name="0.14.7"></a> # [0.14.7](https://github.com/moleculerjs/moleculer/compare/v0.14.6...v0.14.7) (2020-05-22) ## 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** ```js // moleculer.config.js module.exports = { registry: { discoverer: "Local" } } ``` **Example with options** ```js // 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](https://redis.io/) 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** ```js // moleculer.config.js module.exports = { registry: { discoverer: "Redis" } } ``` **Example to connect remote Redis server** ```js // moleculer.config.js module.exports = { registry: { discoverer: "redis://redis-server:6379" } } ``` **Example with options** ```js // 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](https://etcd.io/) to discover Moleculer nodes. The heartbeat & discovery packets are stored in the server. Thanks to etcd3 [lease](https://etcd.io/docs/v3.4.0/learning/api/#lease-api) 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** ```js // moleculer.config.js module.exports = { registry: { discoverer: "Etcd3" } } ``` **Example to connect remote etcd3 server** ```js // moleculer.config.js module.exports = { registry: { discoverer: "etcd3://etcd-server:2379" } } ``` **Example with options** ```js // 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. -------------------------------------------------- <a name="0.14.6"></a> # [0.14.6](https://github.com/moleculerjs/moleculer/compare/v0.14.5...v0.14.6) (2020-04-11) ## New NewRelic zipkin tracing exporter Thanks for [@jalerg](https://github.com/jalerg), there is a NewRelic tracing exporter. [PR #713](https://github.com/moleculerjs/moleculer/pull/713) ```js // 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](https://github.com/moleculerjs/moleculer/pull/712) - fix INFO packet sending issue after reconnecting - safely handling disconnected state for transporters (heartbeat queuing issue). [PR #715](https://github.com/moleculerjs/moleculer/pull/715) - fix orhpan response issue in case of streaming with disabled balancer. [#709](https://github.com/moleculerjs/moleculer/issues/709) - update dependencies, audit fix -------------------------------------------------- <a name="0.14.5"></a> # [0.14.5](https://github.com/moleculerjs/moleculer/compare/v0.14.4...v0.14.5) (2020-03-25) ## Wrapping service methods with middlewares New `localMethod` hook in middlewares which wraps the service methods. **Example** ```js // 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** ```js // 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](https://github.com/moleculerjs/moleculer/issues/683) - add `baseUrl` option to Datadog metric reporter. [#694](https://github.com/moleculerjs/moleculer/issues/694) - fix open handles in unit tests. [#695](https://github.com/moleculerjs/moleculer/issues/695) - update d.ts [#699](https://github.com/moleculerjs/moleculer/issues/699) [#700](https://github.com/moleculerjs/moleculer/issues/700) [#703](https://github.com/moleculerjs/moleculer/issues/703) -------------------------------------------------- <a name="0.14.4"></a> # [0.14.4](https://github.com/moleculerjs/moleculer/compare/v0.14.3...v0.14.4) (2020-03-08) ## Changes - add `maxSafeObjectSize` to service broker options. Fixes [#697](https://github.com/moleculerjs/moleculer/pull/697) - add `stop` method to tracing exporters. Fixes [#689](https://github.com/moleculerjs/moleculer/issues/689) - fix `EventLegacy` tracing exporter. Fixes [#676](https://github.com/moleculerjs/moleculer/issues/676) - the `defaultTags` property in `tracer` options can be a `Function`, as well. -------------------------------------------------- <a name="0.14.3"></a> # [0.14.3](https://github.com/moleculerjs/moleculer/compare/v0.14.2...v0.14.3) (2020-02-24) ## Changes - fix issue in AMQP 1.0 transporter -------------------------------------------------- <a name="0.14.2"></a> # [0.14.2](https://github.com/moleculerjs/moleculer/compare/v0.14.1...v0.14.2) (2020-02-14) ## 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** ```js // 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() }; ``` -------------------------------------------------- <a name="0.14.1"></a> # [0.14.1](https://github.com/moleculerjs/moleculer/compare/v0.14.0...v0.14.1) (2020-02-12) ## Changes - fix bluebird import issue [#674](https://github.com/moleculerjs/moleculer/issues/674) -------------------------------------------------- <a name="0.14.0"></a> # [0.14.0](https://github.com/moleculerjs/moleculer/compare/v0.13.9...v0.14.0) (2020-02-12) [**Migration guide from 0.13 to 0.14**](https://github.com/moleculerjs/moleculer/blob/next/docs/MIGRATION_GUIDE_0.14.md) # Breaking changes ## Minimum Node version is 10 The Node version 8 LTS lifecycle has been ended on December 31, 2019, so the minimum required Node version is 10. ## Bluebird dropped The Bluebird Promise library has been dropped from the project because as of Node 10 the native `Promise` implementation is [faster (2x)](https://github.com/icebob/js-perf-benchmark/blob/95803284dcb46c403eb71f2f114b76bf669189ce/suites/promise.js#L123-L133) than Bluebird. Nonetheless, you can use your desired Promise library, just set the `Promise` broker options. **Using Bluebird** ```js 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). ## Communication protocol has been changed The Moleculer communication protocol has been changed. The new protocol version is `4`. It means the new Moleculer 0.14 nodes can't communicate with old <= 0.13 nodes. ## Fastest validator upgraded to 1.x.x Fastest-validator, the default validation has been upgraded to the 1.0.0 version. It means breaking changes but the new version more faster and contains many sanitization functions. If you use custom rules, you should upgrade your codes. [Check the changes here.](https://github.com/icebob/fastest-validator/releases/tag/v1.0.0-beta1) ## 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](https://github.com/pinojs/pino), [Winston](https://github.com/winstonjs/winston), [Bunyan](https://github.com/trentm/node-bunyan), [Debug](https://github.com/visionmedia/debug) & [Log4js](https://github.com/log4js-node/log4js-node). _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** ```js // moleculer.config.js module.exports = { // Enable console logger logger: true, // Disable all loggers logger: false }; ``` **You CANNOT use these legacy configurations** ```js // 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** ```js // moleculer.config.js module.exports = { logger: "Console", }; ``` **Full configuration** ```js // 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** ```js // 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** ```js // 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", "jsonext", "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](https://github.com/pinojs/pino) logger. **Shorthand configuration with default options** ```js // moleculer.config.js module.exports = { logger: "Pino", }; ``` **Full configuration** ```js // 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](https://github.com/trentm/node-bunyan) logger. **Shorthand configuration with default options** ```js // moleculer.config.js module.exports = { logger: "Bunyan", }; ``` **Full configuration** ```js // 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](https://github.com/winstonjs/winston) logger. **Shorthand configuration with default options** ```js // moleculer.config.js module.exports = { logger: "Winston", }; ``` **Full configuration** ```js // 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](https://github.com/visionmedia/debug) logger. To see messages you have to set the `DEBUG` environment variable to `export DEBUG=moleculer:*`. **Shorthand configuration with default options** ```js // moleculer.config.js module.exports = { logger: "Debug", }; ``` **Full configuration** ```js // 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](https://github.com/log4js-node/log4js-node) logger. **Shorthand configuration with default options** ```js // moleculer.config.js module.exports = { logger: "Log4js", }; ``` **Full configuration** ```js // 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](https://www.datadoghq.com/) 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** ```js // moleculer.config.js module.exports = { logger: "Datadog", }; ``` **Full configuration** ```js // 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. ```js // 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. ```js // 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** ```js // 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", } }; ``` ## Validation settings changed The `validation: true` broker options was removed to follow other module configuration. Use `validator` option, instead. **Enable validation with built-in validator (default option)** ```js const broker = new ServiceBroker({ validator: true }); ``` **Disable validation/validator** ```js const broker = new ServiceBroker({ validator: false }); ``` **Use custom validation** ```js const broker = new ServiceBroker({ validator: new MyCustomValidator() }); ``` ## The `broker.use` removed The `broker.use` has been deprecated in version 0.13 and now it is removed. Use `middleware: []` broker options to define middlewares. _loading middleware after the broker has started is no longer available._ ## The `$node.health` response changed The `$node.health` action's response has been changed. The `transit` property is removed. To get transit metrics, use the new `$node.metrics` internal action. ## Middleware shorthand definition is dropped In previous versions you could define middleware which wraps the `localAction` hook with a simple `Function`. In version 0.14 this legacy shorthand is dropped. When you define a middleware as a `Function`, the middleware handler will call it as an initialization and pass the ServiceBroker instance as a parameter. **Old shorthand middleware definition as a `Function`** ```js const MyMiddleware = function(next, action) { return ctx => next(ctx); }; const broker = new ServiceBroker({ middlewares: [MyMiddleware] }); ``` **New middleware definition as a `Function`** ```js const MyMiddleware = function(broker) { // Create a custom named logger const myLogger = broker.getLogger("MY-LOGGER"); return { localAction: function(next, action) { return ctx => { myLogger.info(`${action.name} has been called`); return next(ctx); } } } }; const broker = new ServiceBroker({ middlewares: [MyMiddleware] }); ``` ## The `localEvent` middleware hook signature changed **Old signature** ```js // my-middleware.js module.exports = { // Wrap local event handlers localEvent(next, event) { return (payload, sender, event) => { return next(payload, sender, event); }; }, }; ``` **New context-based signature** ```js // my-middleware.js module.exports = { // Wrap local event handlers localEvent(next, event) { return (ctx) => { return next(ctx); }; }, }; ``` # New ## Experimental transporters have become stable The Kafka, NATS Streaming & TCP transporter have become stable because we didn't find and receive any issue about them. ## Context-based events The new 0.14 version comes context-based event handler. It is very useful when you are using event-driven architecture and you would like to tracing the event. The Event Context is same as Action Context. They are the same properties except a few new properties related to the event. It doesn't mean you should rewrite all existing event handlers. Moleculer detects the signature of your event handler. If it finds that the signature is `"user.created(ctx) { ... }`, it will call it with Event Context. If not, it will call with old arguments & the 4th argument will be the Event Context, like `"user.created"(payload, sender, eventName, ctx) {...}` **Use Context-based event handler & emit a nested event** ```js module.exports = { name: "accounts", events: { "user.created"(ctx) { console.log("Payload:", ctx.params); console.log("Sender:", ctx.nodeID); console.log("We have also metadata:", ctx.meta); console.log("The called event name:", ctx.eventName); ctx.emit("accounts.created", { user: ctx.params.user }); } } }; ``` If you want to use different variable name or the service can't detect properly the signature, use `context: true` in the event definition: ```js module.exports = { name: "accounts", events: { "user.created": { context: true, handler({ params, nodeID }) { console.log("Payload:", ctx.params); console.log("Sender:", ctx.nodeID); } } } }; ``` ## Event parameter validation Similar to action parameter validation, the event parameter validation is supported. Like in action definition, you should define `params` in even definition and the built-in `Validator` validates the parameters in events. ```js // mailer.service.js module.exports = { name: "mailer", events: { "send.mail": { // Validation schema params: { from: "string|optional", to: "email", subject: "string" }, handler(ctx) { this.logger.info("Event received, parameters OK!", ctx.params); } } } }; ``` >The validation errors are not sent back to the caller, they are logged or you can catch them with the new [global error handler](#global-error-handler). ## New built-in metrics Moleculer v0.14 comes with a brand-new and entirely rewritten metrics module. It is now a built-in module. It collects a lot of internal Moleculer & process metric values. You can easily define your custom metrics. There are several built-in metrics reporters like `Console`, `Prometheus`, `Datadog`, ...etc. Multiple reporters can be defined. **Enable metrics & define console reporter** ```js const broker = new ServiceBroker({ metrics: { enabled: true, reporter: [ "Console" ] } }); ``` **Define custom metrics** ```js // posts.service.js module.exports = { name: "posts", actions: { get(ctx) { // Update metrics this.broker.metrics.increment("posts.get.total"); return posts; } }, cr