diff --git a/.gitignore b/.gitignore index 0982fe30f..8bbf0a28b 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ ct.coverdata .idea/ emqttd.iml _rel/ +data/ diff --git a/Makefile b/Makefile index 1bef9acb6..b57c22aef 100644 --- a/Makefile +++ b/Makefile @@ -1,15 +1,23 @@ PROJECT = emqttd PROJECT_DESCRIPTION = Erlang MQTT Broker -PROJECT_VERSION = 2.0 +PROJECT_VERSION = 3.0 -DEPS = gproc lager gen_logger gen_conf esockd mochiweb +DEPS = gproc lager gen_logger esockd mochiweb getopt pbkdf2 \ + clique time_compat rand_compat -dep_gproc = git https://github.com/uwiger/gproc -dep_lager = git https://github.com/basho/lager -dep_gen_conf = git https://github.com/emqtt/gen_conf -dep_gen_logger = git https://github.com/emqtt/gen_logger -dep_esockd = git https://github.com/emqtt/esockd emq20 -dep_mochiweb = git https://github.com/emqtt/mochiweb +dep_gproc = git https://github.com/uwiger/gproc +dep_getopt = git https://github.com/jcomellas/getopt v0.8.2 +dep_lager = git https://github.com/basho/lager master +dep_gen_logger = git https://github.com/emqtt/gen_logger +dep_esockd = git https://github.com/emqtt/esockd emq20 +dep_mochiweb = git https://github.com/emqtt/mochiweb +dep_clique = git https://github.com/basho/clique +dep_pbkdf2 = git https://github.com/basho/erlang-pbkdf2 2.0.0 +dep_time_compat = git https://github.com/lasp-lang/time_compat +dep_rand_compat = git https://github.com/lasp-lang/rand_compat + +BUILD_DEPS = cuttlefish +dep_cuttlefish = git https://github.com/basho/cuttlefish master ERLC_OPTS += +'{parse_transform, lager_transform}' @@ -29,3 +37,6 @@ include erlang.mk app:: rebar.config +app.config:: + cuttlefish -l info -e etc/ -c etc/emqttd.conf -i priv/emqttd.schema -d data + diff --git a/etc/emqttd.2.0.conf b/etc/emqttd.2.0.conf new file mode 100644 index 000000000..98b460e86 --- /dev/null +++ b/etc/emqttd.2.0.conf @@ -0,0 +1,252 @@ + +%%-------------------------------------------------------------------- +%% MQTT Protocol +%%-------------------------------------------------------------------- + +%% Max ClientId Length Allowed. +{mqtt_max_clientid_len, 512}. + +%% Max Packet Size Allowed, 64K by default. +{mqtt_max_packet_size, 65536}. + +%% Client Idle Timeout. +{mqtt_client_idle_timeout, 30}. % Second + +%%-------------------------------------------------------------------- +%% Authentication +%%-------------------------------------------------------------------- + +%% Anonymous: Allow all +{auth, anonymous, []}. + +%% Authentication with username, password +{auth, username, [{passwd, "etc/modules/passwd.conf"}]}. + +%% Authentication with clientId +{auth, clientid, [{config, "etc/modules/client.conf"}, {password, no}]}. + +%%-------------------------------------------------------------------- +%% ACL +%%-------------------------------------------------------------------- + +{acl, anonymous, []}. + +{acl, internal, [{config, "etc/modules/acl.conf"}, {nomatch, allow}]}. + +%% Cache ACL result for PUBLISH +{cache_acl, true}. + + +%%-------------------------------------------------------------------- +%% Session +%%-------------------------------------------------------------------- + +%% Max number of QoS 1 and 2 messages that can be “inflight” at one time. +%% 0 means no limit +{session_max_inflight, 100}. + +%% Retry interval for redelivering QoS1/2 messages. +{session_unack_retry_interval, 60}. + +%% Awaiting PUBREL Timeout +{session_await_rel_timeout, 20}. + +%% Max Packets that Awaiting PUBREL, 0 means no limit +{session_max_awaiting_rel, 0}. + +%% Statistics Collection Interval(seconds) +{session_collect_interval, 0}. + +%% Expired after 2 day (unit: minute) +{session_expired_after, 2880}. + +%%-------------------------------------------------------------------- +%% Queue +%%-------------------------------------------------------------------- + +%% Type: simple | priority +{queue_type, simple}. + +%% Topic Priority: 0~255, Default is 0 +%% {queue_priority, [{"topic/1", 10}, {"topic/2", 8}]}. + +%% Max queue length. Enqueued messages when persistent client disconnected, +%% or inflight window is full. +{queue_max_length, infinity}. + +%% Low-water mark of queued messages +{queue_low_watermark, 0.2}. + +%% High-water mark of queued messages +{queue_high_watermark, 0.6}. + +%% Queue Qos0 messages? +{queue_qos0, true}. + +%%-------------------------------------------------------------------- +%% Listener +%%-------------------------------------------------------------------- + +%% Plain MQTT +{listener, mqtt, 1883, [ + %% Size of acceptor pool + {acceptors, 16}, + + %% Maximum number of concurrent clients + {max_clients, 512}, + + %% Mount point prefix + %% {mount_point, "prefix/"}, + + %% Socket Access Control + {access, [{allow, all}]}, + + %% Connection Options + {connopts, [ + %% Rate Limit. Format is 'burst, rate', Unit is KB/Sec + %% {rate_limit, "100,10"} %% 100K burst, 10K rate + ]}, + + %% Socket Options + {sockopts, [ + %Set buffer if hight thoughtput + %{recbuf, 4096}, + %{sndbuf, 4096}, + %{buffer, 4096}, + %{nodelay, true}, + {backlog, 1024} + ]} +]}. + +%% MQTT/SSL +{listener, mqtts, 8883, [ + %% Size of acceptor pool + {acceptors, 4}, + + %% Maximum number of concurrent clients + {max_clients, 512}, + + %% Mount point prefix + %% {mount_point, "secure/"}, + + %% Socket Access Control + {access, [{allow, all}]}, + + %% SSL certificate and key files + {ssl, [{handshake_timeout, 10000}, + %% Mutual SSL Authentication option + %% {verify, verify_peer}, + %% {cacertfile, "etc/ssl/ca.pem"}, + {certfile, "etc/ssl/ssl.crt"}, + {keyfile, "etc/ssl/ssl.key"}]}, + + %% Socket Options + {sockopts, [ + {backlog, 1024} + %{buffer, 4096}, + ]} +]}. + +%% HTTP and WebSocket Listener +{listener, http, 8083, [ + %% Size of acceptor pool + {acceptors, 4}, + + %% Maximum number of concurrent clients + {max_clients, 64}, + + %% Socket Access Control + {access, [{allow, all}]}, + + %% Socket Options + {sockopts, [ + {backlog, 1024} + %{buffer, 4096}, + ]} +]}. + +%%-------------------------------------------------------------------- +%% PubSub +%%-------------------------------------------------------------------- + +%% PubSub Pool Size. Default should be scheduler numbers. +{pubsub_pool_size, 8}. + +{pubsub_by_clientid, true}. + +%% Subscribe Asynchronously +{pubsub_async, true}. + +%%-------------------------------------------------------------------- +%% Bridge +%%-------------------------------------------------------------------- + +%% TODO: Bridge Queue Size +{bridge_max_queue_len, 10000}. + +%% Ping Interval of bridge node +{bridge_ping_down_interval, 1}. % second + +%%------------------------------------------------------------------- +%% Plugins +%%------------------------------------------------------------------- + +%% Dir of plugins' config +{plugins_etc_dir, "etc/plugins/"}. + +%% File to store loaded plugin names. +{plugins_loaded_file, "data/loaded_plugins"}. + +%%-------------------------------------------------------------------- +%% Modules +%%-------------------------------------------------------------------- + +%% Retainer Module +{module, retainer, [ + + %% disc: disc_copies, ram: ram_copies + {storage_type, disc}, + + %% Max number of retained messages + {max_message_num, 100000}, + + %% Max Payload Size of retained message + {max_playload_size, 65536}, + + %% Expired after seconds, never expired if 0 + {expired_after, 0} + +]}. + +%% Client presence management module. Publish presence messages when +%% client connected or disconnected. +{module, presence, [{qos, 0}]}. + +%% Subscribe topics automatically when client connected +{module, subscription, [{"$client/%c", 1}]}. + +%% [Rewrite](https://github.com/emqtt/emqttd/wiki/Rewrite) +%% {module, rewrite, [{config, "etc/modules/rewrite.conf"}]}. + +%%------------------------------------------------------------------- +%% Erlang System Monitor +%%------------------------------------------------------------------- + +%% Long GC, don't monitor in production mode for: +%% https://github.com/erlang/otp/blob/feb45017da36be78d4c5784d758ede619fa7bfd3/erts/emulator/beam/erl_gc.c#L421 + +{sysmon_long_gc, false}. + +%% Long Schedule(ms) +{sysmon_long_schedule, 240}. + +%% 8M words. 32MB on 32-bit VM, 64MB on 64-bit VM. +%% 8 * 1024 * 1024 +{sysmon_large_heap, 8388608}. + +%% Busy Port +{sysmon_busy_port, false}. + +%% Busy Dist Port +{sysmon_busy_dist_port, true}. + diff --git a/etc/emqttd.conf b/etc/emqttd.conf new file mode 100644 index 000000000..e2cce52e7 --- /dev/null +++ b/etc/emqttd.conf @@ -0,0 +1,192 @@ +##==================================================================== +## +## Config File for EMQ 3.0 +## +##==================================================================== + +##-------------------------------------------------------------------- +## Erlang VM Args +##-------------------------------------------------------------------- + +## Erlang Node Name +vm.nodename = emqttd@127.0.0.1 + +## Cookie for distributed erlang +vm.setcookie = emqttdsecretcookie + +## SMP support: enable, auto, disable +vm.smp = auto + +## Enable kernel poll +vm.kernel_poll = on + +## async thread pool +vm.async_threads = 32 + +## Erlang Process Limit +vm.process_limit = 256000 + +## Sets the maximum number of simultaneously existing ports for this system +vm.max_ports = 262144 + +## Set the distribution buffer busy limit (dist_buf_busy_limit) +vm.dist_buffer_size = 32MB + +## Max ETS Tables. +## Note that mnesia and SSL will create temporary ets tables. +vm.max_ets_tables = 256000 + +## Tweak GC to run more often +vm.fullsweep_after = 1000 + +vm.crash_dump = log/emqttd_crash.dump + +##-------------------------------------------------------------------- +## MQTT Protocol +##-------------------------------------------------------------------- + +## Max ClientId Length Allowed. +mqtt.max_clientid_len = 1024 + +## Max Packet Size Allowed, 64K by default. +mqtt.max_packet_size = 64KB + +## Client Idle Timeout (Second) +mqtt.client_idle_timeout = 30 + +##-------------------------------------------------------------------- +## MQTT Listeners +##-------------------------------------------------------------------- + +## {listener, mqtt, 1883, [ +## %% Size of acceptor pool +## {acceptors, 16}, +## %% Maximum number of concurrent clients +## {max_clients, 512}, +## %% Mount point prefix +## %% {mount_point, "prefix/"}, +## %% Socket Access Control +## {access, [{allow, all}]}, +## %% Connection Options +## {connopts, [ +## %% Rate Limit. Format is 'burst, rate', Unit is KB/Sec +## %% {rate_limit, "100,10"} %% 100K burst, 10K rate +## ]}, +## %% Socket Options +## {sockopts, [ +## %Set buffer if hight thoughtput +## %{recbuf, 4096}, +## %{sndbuf, 4096}, +## %{buffer, 4096}, +## %{nodelay, true}, +## {backlog, 1024} +## ]} +## ]}. + +listener.mqtt.plain = 1883 +## IPv6 +## listener.mqtt = 127.0.0.1:1883 +## IPv6 +## listener.mqtt = ::1:1883 +listener.mqtt.plain.acceptors = 16 +listener.mqtt.plain.max_clients = 512 +listener.mqtt.plain.rate_limit = 100,10 +listener.mqtt.plain.mount_point = prefix/ + +listener.mqtts = 8883 +listener.mqtts.acceptors = 4 +listener.mqtts.max_clients = 512 +listener.mqtts.ssl. + + %% SSL certificate and key files + {ssl, [{handshake_timeout, 10000}, + %% Mutual SSL Authentication option + %% {verify, verify_peer}, + %% {cacertfile, "etc/ssl/ca.pem"}, + {certfile, "etc/ssl/ssl.crt"}, + {keyfile, "etc/ssl/ssl.key"}]}, + +listener.http = 8083 + +##-------------------------------------------------------------------- +## MQTT Session +##-------------------------------------------------------------------- + +## Max number of QoS 1 and 2 messages that can be “inflight” at one time. +## 0 means no limit +mqtt.session.max_inflight = 100 + +## Retry interval for redelivering QoS1/2 messages. +mqtt.session.unack_retry_interval = 60 + +## Awaiting PUBREL Timeout +mqtt.session.await_rel_timeout = 20 + +## Max Packets that Awaiting PUBREL, 0 means no limit +mqtt.session.max_awaiting_rel = 0 + +## Statistics Collection Interval(seconds) +mqtt.session.collect_interval = 0 + +## Expired after 2 day (unit: minute) +mqtt.session.expired_after = 2880 + +##-------------------------------------------------------------------- +## MQTT Queue Parameters +##-------------------------------------------------------------------- + +## Type: simple | priority +mqtt.queue_type = simple + +## Topic Priority: 0~255, Default is 0 +## mqtt.queue_priority = topic/1=10,topic/2=8 + +## Max queue length. Enqueued messages when persistent client disconnected, +## or inflight window is full. +mqtt.queue_max_length = infinity + +## Low-water mark of queued messages +mqtt.queue_low_watermark = 0.2 + +## High-water mark of queued messages +mqtt.queue_high_watermark = 0.6 + +## Queue Qos0 messages? +mqtt.queue_qos0 = true + +##-------------------------------------------------------------------- +## Broker +##-------------------------------------------------------------------- + +## System Interval of publishing broker $SYS Messages +broker.sys_interval = 60 + + +##------------------------------------------------------------------- +## Log +##------------------------------------------------------------------- + + + +##------------------------------------------------------------------- +## System Monitor +##------------------------------------------------------------------- + +## Long GC, don't monitor in production mode for: +## https://github.com/erlang/otp/blob/feb45017da36be78d4c5784d758ede619fa7bfd3/erts/emulator/beam/erl_gc.c#L421 + +sysmon.long_gc = false + +## Long Schedule(ms) +sysmon.long_schedule = 240 + +## 8M words. 32MB on 32-bit VM, 64MB on 64-bit VM. +## 8 * 1024 * 1024 +sysmon.large_heap = 8388608 + +## Busy Port +sysmon.busy_port = false + +## Busy Dist Port +sysmon.busy_dist_port = true + diff --git a/etc/emqttd.conf.3 b/etc/emqttd.conf.3 new file mode 100644 index 000000000..a353e48d0 --- /dev/null +++ b/etc/emqttd.conf.3 @@ -0,0 +1,210 @@ +##=================================================================== +## +## Config file for EMQ 3.0 +## +##=================================================================== + +##-------------------------------------------------------------------- +## Authentication +##-------------------------------------------------------------------- + +%% Anonymous: Allow all +{auth, anonymous, []}. + +%% Authentication with username, password +{auth, username, [{passwd, "etc/modules/passwd.conf"}]}. + +%% Authentication with clientId +{auth, clientid, [{config, "etc/modules/client.conf"}, {password, no}]}. + +%%-------------------------------------------------------------------- +%% ACL +%%-------------------------------------------------------------------- + +{acl, anonymous, []}. + +{acl, internal, [{config, "etc/modules/acl.conf"}, {nomatch, allow}]}. + +%% Cache ACL result for PUBLISH +{cache_acl, true}. + +##-------------------------------------------------------------------- +## Broker +##-------------------------------------------------------------------- + +## System interval of publishing broker $SYS messages +broker.sys_interval = 60. + +##-------------------------------------------------------------------- +## Session +##-------------------------------------------------------------------- + + + +%%-------------------------------------------------------------------- +%% Listener +%%-------------------------------------------------------------------- + +%% Plain MQTT +{listener, mqtt, 1883, [ + %% Size of acceptor pool + {acceptors, 16}, + + %% Maximum number of concurrent clients + {max_clients, 512}, + + %% Mount point prefix + %% {mount_point, "prefix/"}, + + %% Socket Access Control + {access, [{allow, all}]}, + + %% Connection Options + {connopts, [ + %% Rate Limit. Format is 'burst, rate', Unit is KB/Sec + %% {rate_limit, "100,10"} %% 100K burst, 10K rate + ]}, + + %% Socket Options + {sockopts, [ + %Set buffer if hight thoughtput + %{recbuf, 4096}, + %{sndbuf, 4096}, + %{buffer, 4096}, + %{nodelay, true}, + {backlog, 1024} + ]} +]}. + +%% MQTT/SSL +{listener, mqtts, 8883, [ + %% Size of acceptor pool + {acceptors, 4}, + + %% Maximum number of concurrent clients + {max_clients, 512}, + + %% Mount point prefix + %% {mount_point, "secure/"}, + + %% Socket Access Control + {access, [{allow, all}]}, + + %% SSL certificate and key files + {ssl, [{handshake_timeout, 10000}, + %% Mutual SSL Authentication option + %% {verify, verify_peer}, + %% {cacertfile, "etc/ssl/ca.pem"}, + {certfile, "etc/ssl/ssl.crt"}, + {keyfile, "etc/ssl/ssl.key"}]}, + + %% Socket Options + {sockopts, [ + {backlog, 1024} + %{buffer, 4096}, + ]} +]}. + +%% HTTP and WebSocket Listener +{listener, http, 8083, [ + %% Size of acceptor pool + {acceptors, 4}, + + %% Maximum number of concurrent clients + {max_clients, 64}, + + %% Socket Access Control + {access, [{allow, all}]}, + + %% Socket Options + {sockopts, [ + {backlog, 1024} + %{buffer, 4096}, + ]} +]}. + +%%-------------------------------------------------------------------- +%% PubSub +%%-------------------------------------------------------------------- + +%% PubSub Pool Size. Default should be scheduler numbers. +{pubsub_pool_size, 8}. + +{pubsub_by_clientid, true}. + +%% Subscribe Asynchronously +{pubsub_async, true}. + +%%-------------------------------------------------------------------- +%% Bridge +%%-------------------------------------------------------------------- + +%% TODO: Bridge Queue Size +{bridge_max_queue_len, 10000}. + +%% Ping Interval of bridge node +{bridge_ping_down_interval, 1}. % second + +%%------------------------------------------------------------------- +%% Plugins +%%------------------------------------------------------------------- + +%% Dir of plugins' config +{plugins_etc_dir, "etc/plugins/"}. + +%% File to store loaded plugin names. +{plugins_loaded_file, "data/loaded_plugins"}. + +%%-------------------------------------------------------------------- +%% Modules +%%-------------------------------------------------------------------- + +%% Retainer Module +{module, retainer, [ + + %% disc: disc_copies, ram: ram_copies + {storage_type, disc}, + + %% Max number of retained messages + {max_message_num, 100000}, + + %% Max Payload Size of retained message + {max_playload_size, 65536}, + + %% Expired after seconds, never expired if 0 + {expired_after, 0} + +]}. + +%% Client presence management module. Publish presence messages when +%% client connected or disconnected. +{module, presence, [{qos, 0}]}. + +%% Subscribe topics automatically when client connected +{module, subscription, [{"$client/%c", 1}]}. + +%% [Rewrite](https://github.com/emqtt/emqttd/wiki/Rewrite) +%% {module, rewrite, [{config, "etc/modules/rewrite.conf"}]}. + +%%------------------------------------------------------------------- +%% Erlang System Monitor +%%------------------------------------------------------------------- + +%% Long GC, don't monitor in production mode for: +%% https://github.com/erlang/otp/blob/feb45017da36be78d4c5784d758ede619fa7bfd3/erts/emulator/beam/erl_gc.c#L421 + +sysmon.long_gc = false + +%% Long Schedule(ms) +sysmon.long_schedule = 240 + +%% 8M words. 32MB on 32-bit VM, 64MB on 64-bit VM. +%% 8 * 1024 * 1024 +sysmon.large_heap = 8388608 + +%% Busy Port +sysmon.busy_port = false + +%% Busy Dist Port +sysmon.busy_dist_port = true + diff --git a/priv/emqttd.schema b/priv/emqttd.schema new file mode 100644 index 000000000..2b5311462 --- /dev/null +++ b/priv/emqttd.schema @@ -0,0 +1,374 @@ +%%-*- mode: erlang -*- +%% EMQ 3.0 Config Mapping + +%%-------------------------------------------------------------------- +%% Erlang VM Args +%%-------------------------------------------------------------------- + +{mapping, "vm.nodename", "vm_args.-name", [ + {default, "{{node}}"} +]}. + +{mapping, "vm.setcookie", "vm_args.-setcookie", [ + {default, "emqttd"} +]}. + +{mapping, "vm.smp", "vm_args.-smp", [ + {default, enable}, + {datatype, {enum, [enable, auto, disable]}}, + hidden +]}. + +{mapping, "vm.kernel_poll", "vm_args.+K", [ + {default, on}, + {datatype, flag}, + hidden +]}. + +%% More information at: http://erlang.org/doc/man/erl.html +{mapping, "vm.async_threads", "vm_args.+A", [ + {default, 64}, + {datatype, integer}, + {validators, ["range:0-1024"]} +]}. + +%% @doc Erlang Process Limit +{mapping, "vm.process_limit", "vm_args.+P", [ + {datatype, integer}, + {default, 256000}, + hidden +]}. + +%% Note: OTP R15 and earlier uses -env ERL_MAX_PORTS, R16+ uses +Q +%% @doc The number of concurrent ports/sockets +%% Valid range is 1024-134217727 +{mapping, "vm.max_ports", + cuttlefish:otp("R16", "vm_args.+Q", "vm_args.-env ERL_MAX_PORTS"), [ + {default, 262144}, + {datatype, integer}, + {validators, ["range4ports"]} +]}. + +{validator, "range4ports", "must be 1024 to 134217727", + fun(X) -> X >= 1024 andalso X =< 134217727 end}. + +%% @doc For nodes with many busy_dist_port events, Basho recommends +%% raising the sender-side network distribution buffer size. +%% 32MB may not be sufficient for some workloads and is a suggested +%% starting point. Erlangers may know this as +zdbbl. +%% The Erlang/OTP default is 1024 (1 megabyte). +%% See: http://www.erlang.org/doc/man/erl.html#%2bzdbbl +{mapping, "vm.dist_buffer_size", "vm_args.+zdbbl", [ + {datatype, bytesize}, + {commented, "32MB"}, + hidden, + {validators, ["zdbbl_range"]} +]}. + +{translation, "vm_args.+zdbbl", + fun(Conf) -> + ZDBBL = cuttlefish:conf_get("vm.dist_buffer_size", Conf, undefined), + case ZDBBL of + undefined -> undefined; + X when is_integer(X) -> cuttlefish_util:ceiling(X / 1024); %% Bytes to Kilobytes; + _ -> undefined + end + end +}. + +{validator, "zdbbl_range", "must be between 1KB and 2097151KB", + fun(ZDBBL) -> + %% 2097151KB = 2147482624 + ZDBBL >= 1024 andalso ZDBBL =< 2147482624 + end +}. + +%% @doc A non-negative integer which indicates how many times +%% generational garbage collections can be done without forcing a +%% fullsweep collection. In low-memory systems (especially without +%% virtual memory), setting the value to 0 can help to conserve +%% memory. +%% +%% More information at: +%% http://www.erlang.org/doc/man/erlang.html#system_flag-2 +{mapping, "vm.fullsweep_after", "vm_args.-env ERL_FULLSWEEP_AFTER", [ + {default, 1000}, + {datatype, integer}, + hidden, + {validators, ["positive_integer"]} +]}. + +{validator, "positive_integer", "must be a positive integer", + fun(X) -> X >= 0 end}. + +%% Note: OTP R15 and earlier uses -env ERL_MAX_ETS_TABLES, +%% R16+ uses +e +%% @doc Raise the ETS table limit +{mapping, "vm.max_ets_tables", + cuttlefish:otp("R16", "vm_args.+e", "vm_args.-env ERL_MAX_ETS_TABLES"), [ + {default, 256000}, + {datatype, integer}, + hidden +]}. + +%% @doc Set the location of crash dumps +{mapping, "vm.crash_dump", "vm_args.-env ERL_CRASH_DUMP", [ + {default, "{{crash_dump}}"}, + {datatype, file}, + hidden +]}. + +{mapping, "mqtt.max_clientid_len", "emqttd.mqtt_max_clientid_len", [ + {default, 1024}, + {datatype, integer} +]}. + +{mapping, "mqtt.max_packet_size", "emqttd.mqtt_max_packet_size", [ + {datatype, bytesize} +]}. + +{mapping, "mqtt.client_idle_timeout", "emqttd.mqtt_client_idle_timeout", [ + {datatype, integer} +]}. + +{mapping, "sysmon.long_gc", "emqttd.sysmon", [ + {default, false}, + {datatype, {enum, [true, false]}} +]}. + +{mapping, "sysmon.long_schedule", "emqttd.sysmon", [ + {default, 1000}, + {datatype, integer} +]}. + +{mapping, "sysmon.large_heap", "emqttd.sysmon", [ + {datatype, integer} +]}. + +{mapping, "sysmon.busy_port", "emqttd.sysmon", [ + {default, false}, + {datatype, {enum, [true, false]}} +]}. + +{mapping, "sysmon.busy_dist_port", "emqttd.sysmon", [ + {default, true}, + {datatype, {enum, [true, false]}} +]}. + +{translation, "emqttd.sysmon", fun(Conf) -> + [{long_gc, cuttlefish:conf_get("sysmon.long_gc", Conf)}, + {long_schedule, cuttlefish:conf_get("sysmon.long_schedule", Conf)}, + {large_heap, cuttlefish:conf_get("sysmon.large_heap", Conf)}, + {busy_port, cuttlefish:conf_get("sysmon.busy_port", Conf)}, + {busy_dist_port, cuttlefish:conf_get("sysmon.busy_dist_port", Conf)}] +end}. + +%% @doc Where to emit the default log messages (typically at 'info' +%% severity): +%% off: disabled +%% file: the file specified by log.console.file +%% console: to standard output (seen when using `riak attach-direct`) +%% both: log.console.file and standard out. +{mapping, "log.console", "lager.handlers", [ + {default, file }, + {datatype, {enum, [off, file, console, both]}} +]}. + +%% @doc The severity level of the console log, default is 'info'. +{mapping, "log.console.level", "lager.handlers", [ + {default, info}, + {datatype, {enum, [debug, info, notice, warning, error, critical, alert, emergency, none]}} +]}. + +%% @doc When 'log.console' is set to 'file' or 'both', the file where +%% console messages will be logged. +{mapping, "log.console.file", "lager.handlers", [ + {default, "$(platform_log_dir)/console.log"}, + {datatype, file} +]}. + +%% @doc The file where error messages will be logged. +{mapping, "log.error.file", "lager.handlers", [ + {default, "$(platform_log_dir)/error.log"}, + {datatype, file} +]}. + +%% @doc When set to 'on', enables log output to syslog. +{mapping, "log.syslog", "lager.handlers", [ + {default, off}, + {datatype, flag} +]}. + +%% @doc When set to 'on', enables log output to syslog. +{mapping, "log.syslog.ident", "lager.handlers", [ + {default, "riak"}, + hidden +]}. + +%% @doc Syslog facility to log entries from Riak. +{mapping, "log.syslog.facility", "lager.handlers", [ + {default, daemon}, + {datatype, {enum,[kern, user, mail, daemon, auth, syslog, + lpr, news, uucp, clock, authpriv, ftp, + cron, local0, local1, local2, local3, + local4, local5, local6, local7]}}, + hidden +]}. + +%% @doc The severity level at which to log entries to syslog, default is 'info'. +{mapping, "log.syslog.level", "lager.handlers", [ + {default, info}, + {datatype, {enum, [debug, info, notice, warning, error, critical, alert, emergency, none]}}, + hidden +]}. + +{translation, + "lager.handlers", + fun(Conf) -> + SyslogHandler = case cuttlefish:conf_get("log.syslog", Conf) of + true -> + Ident = cuttlefish:conf_get("log.syslog.ident", Conf), + Facility = cuttlefish:conf_get("log.syslog.facility", Conf), + LogLevel = cuttlefish:conf_get("log.syslog.level", Conf), + [{lager_syslog_backend, [Ident, Facility, LogLevel]}]; + _ -> [] + end, + ErrorHandler = case cuttlefish:conf_get("log.error.file", Conf) of + undefined -> []; + ErrorFilename -> [{lager_file_backend, [{file, ErrorFilename}, + {level, error}, + {size, 10485760}, + {date, "$D0"}, + {count, 5}]}] + end, + + ConsoleLogLevel = cuttlefish:conf_get("log.console.level", Conf), + ConsoleLogFile = cuttlefish:conf_get("log.console.file", Conf), + + ConsoleHandler = {lager_console_backend, ConsoleLogLevel}, + ConsoleFileHandler = {lager_file_backend, [{file, ConsoleLogFile}, + {level, ConsoleLogLevel}, + {size, 10485760}, + {date, "$D0"}, + {count, 5}]}, + + ConsoleHandlers = case cuttlefish:conf_get("log.console", Conf) of + off -> []; + file -> [ConsoleFileHandler]; + console -> [ConsoleHandler]; + both -> [ConsoleHandler, ConsoleFileHandler]; + _ -> [] + end, + SyslogHandler ++ ConsoleHandlers ++ ErrorHandler + end +}. + + +%% @doc Whether to enable Erlang's built-in error logger. +{mapping, "sasl", "sasl.sasl_error_logger", [ + {default, off}, + {datatype, flag}, + hidden +]}. + +%% @doc Whether to enable the crash log. +{mapping, "log.crash", "lager.crash_log", [ + {default, on}, + {datatype, flag} +]}. + +%% @doc If the crash log is enabled, the file where its messages will +%% be written. +{mapping, "log.crash.file", "lager.crash_log", [ + {default, "$(platform_log_dir)/crash.log"}, + {datatype, file} +]}. + +{translation, + "lager.crash_log", + fun(Conf) -> + case cuttlefish:conf_get("log.crash", Conf) of + false -> undefined; + _ -> + cuttlefish:conf_get("log.crash.file", Conf, "./log/crash.log") + end + end}. + +%% @doc Maximum size in bytes of individual messages in the crash log +{mapping, "log.crash.maximum_message_size", "lager.crash_log_msg_size", [ + {default, "64KB"}, + {datatype, bytesize} +]}. + +%% @doc Maximum size of the crash log in bytes, before it is rotated +{mapping, "log.crash.size", "lager.crash_log_size", [ + {default, "10MB"}, + {datatype, bytesize} +]}. + +%% @doc The schedule on which to rotate the crash log. For more +%% information see: +%% https://github.com/basho/lager/blob/master/README.md#internal-log-rotation +{mapping, "log.crash.rotation", "lager.crash_log_date", [ + {default, "$D0"} +]}. + +%% @doc The number of rotated crash logs to keep. When set to +%% 'current', only the current open log file is kept. +{mapping, "log.crash.rotation.keep", "lager.crash_log_count", [ + {default, 5}, + {datatype, [integer, {atom, current}]}, + {validators, ["rotation_count"]} +]}. + +{validator, + "rotation_count", + "must be 'current' or a positive integer", + fun(current) -> true; + (Int) when is_integer(Int) andalso Int >= 0 -> true; + (_) -> false + end}. + +{translation, + "lager.crash_log_count", + fun(Conf) -> + case cuttlefish:conf_get("log.crash.rotation.keep", Conf) of + current -> 0; + Int -> Int + end + end}. + +%% @doc Whether to redirect error_logger messages into lager - +%% defaults to true +{mapping, "log.error.redirect", "lager.error_logger_redirect", [ + {default, on}, + {datatype, flag}, + hidden +]}. + +%% @doc Maximum number of error_logger messages to handle in a second +{mapping, "log.error.messages_per_second", "lager.error_logger_hwm", [ + {default, 100}, + {datatype, integer}, + hidden +]}. + + +%% @doc Cookie for distributed node communication. All nodes in the +%% same cluster should use the same cookie or they will not be able to +%% communicate. +{mapping, "distributed_cookie", "vm_args.-setcookie", [ + {default, "riak"} +]}. + +%% @see platform_bin_dir +{mapping, "platform_etc_dir", "emqttd.platform_etc_dir", [ + {datatype, directory}, + {default, "./etc"} +]}. + +%% @see platform_bin_dir +{mapping, "platform_log_dir", "emqttd.platform_log_dir", [ + {datatype, directory}, + {default, "./log"} +]}. diff --git a/rebar.config b/rebar.config index 74a744b0d..f30238fd7 100644 --- a/rebar.config +++ b/rebar.config @@ -1,4 +1,4 @@ {deps, [ -{gproc,".*",{git,"https://github.com/uwiger/gproc",""}},{lager,".*",{git,"https://github.com/basho/lager",""}},{gen_logger,".*",{git,"https://github.com/emqtt/gen_logger",""}},{gen_conf,".*",{git,"https://github.com/emqtt/gen_conf",""}},{esockd,".*",{git,"https://github.com/emqtt/esockd","emq20"}},{mochiweb,".*",{git,"https://github.com/emqtt/mochiweb",""}} +{gproc,".*",{git,"https://github.com/uwiger/gproc",""}},{lager,".*",{git,"https://github.com/basho/lager","master"}},{gen_logger,".*",{git,"https://github.com/emqtt/gen_logger",""}},{esockd,".*",{git,"https://github.com/emqtt/esockd","emq20"}},{mochiweb,".*",{git,"https://github.com/emqtt/mochiweb",""}},{getopt,".*",{git,"https://github.com/jcomellas/getopt","v0.8.2"}},{pbkdf2,".*",{git,"https://github.com/basho/erlang-pbkdf2","2.0.0"}},{clique,".*",{git,"https://github.com/basho/clique",""}},{time_compat,".*",{git,"https://github.com/lasp-lang/time_compat",""}},{rand_compat,".*",{git,"https://github.com/lasp-lang/rand_compat",""}} ]}. {erl_opts, [{parse_transform,lager_transform}]}.