10个好用的Erlang工具

10 Essential Erlang Tools for Erlang Developers

Introduction

In this tutorial, I'll cover the tools that I use the most in my day-to-day life as an Erlang developer. All or most of the topics that make the cut share the following characteristics:

  • they're built specifically for Erlang (i.e. no text-editors, no git, etc.).
  • they're not tailored to a particular kind of application (i.e. you can use them to develop any kind of Erlang application).

Working in the Shell

Like many other languages, the most common way to interact with an Erlang VM is through the Erlang shell. You can use it to test code, learn how to use Erlang, and debug production systems. The Erlang shell is a powerful thing, but you can add much more power to it with the three tools that I will show you below.

image: https://c2.staticflickr.com/8/7059/6886658738_d371a49e54_b.jpg

I see a blondie

1. user_default 

In general, to evaluate functions outside a module in Erlang you have to prepend their names with the corresponding module name. For example, if you want to sum up a list, you have to do the following:

1> lists:sum([1, 2, 3]).
6
2>

But you'll notice that for certain functions in the shell, you don't need explicit definitions. For example:

1> c(your_module).
{ok,your_module}
2> h().
1: c(your_module)
-> {ok,your_module}
ok
3> e(1).
{ok,your_module}
4>

Where do such functions live? They're defined in the shell_default  module. You can add your own default functions as well. To do that, you have to create and load a module called user_default. As an example, I like to run bash commands when using the Erlang shell; I don't want to leave the shell just to copy a file. Erlang/OTP gives you a a function to do that: os:cmd/1, but that will not print out the output of your command. Instead this command will return that output as a string. You have to print the string to see the output properly.

So, using user_default, I added the following lines to my user_default.erl file:

-module(user_default).
-export([cmd/1].

cmd(Cmd) -> io:format("~s~n", [os:cmd(Cmd)]).

Now I can run, execute, and print the results of os:cmd/1 using my shell:

1> c(user_default).
{ok, user_default}
2> cmd("cat user_default.erl").
-module(user_default).
-export([cmd/1].

cmd(Cmd) -> io:format("~s~n", [os:cmd(Cmd)]).

ok
3>

2. ~/.erlang 

But then, I have to manually load user_default in every single shell that I open. ~/.erlang to the rescue! ~/.erlang is a file that works almost like ~/.bashrc for bash. Upon starting, the shell reads ~/.erlang and evaluates each one of the expressions it finds there as if they were inputted to the shell.

So, I added the following lines to that file:

UD = "/path/to/my/user_default".
shell_default:c(UD).

My ~/.erlang is actually more complicated than that, but the shell_default should give you the gist of my modifications. Now, every shell that I open comes with support for cmd/1.

3. erlang-history 

One of the most annoying things about the Erlang shell is that it does not keep track of command history very well. In fact, default settings will erase all command history upon closing the shell. I've seen many devs working around this limitation by having a notebook of erlang expressions from which they copy & paste into the console every time. (Some of them use user_default and/or ~/.erlang for that.)

But still, it's not a real solution, right? To properly fix the issue, right after installing a new version of Erlang/OTP, I install erlang-history . It's a really tiny almost-invisible hack to the Erlang/OTP distribution with one simple purpose: to keep track of your previous commands in your Erlang shells and let you reuse them. Simple, yet amazingly useful.


Managing your Apps

As soon as you move past the simple examples and into the realm of OTP apps, you'll be much better off working with a build tool that can help you organize your code, manage dependencies, build releases, run tests, and more.

image: http://www.tierragamer.com/wp-content/uploads/2016/02/its-dangerous-to-go-alone-take-this.jpg

Dangerous to go Alone

When working with Erlang, you can either embrace the Makefile or try get as far away from it as possible.

4. erlang.mk 

If using Makefiles to build and manage your projects seems natural to you, you will probably like erlang.mk erlang.mk is basically a big Makefile script that you can include in your own Makefile with something like:

PROJECT=your_app
include erlang.mk

With that, you get access to many commands, like

  • $ make to build your project
  • $ make tests to run your test suites
  • $ make rel to generate a release

You can find the whole list using $ make help, and you can, of course, add more by just extending your Makefile.

erlang.mk also provides a plugin infrastructure, where you can add build tools, like hexer.mk  or elvis.mk .

The best thing about erlang.mk is that it provides the necessary support for building almost any existing Erlang library, regardless of the tool that library owners use to maintain it. With erlang.mk you can include applications built with rebarrebar3erlang.mk (as expected :P), ad-hoc Makefiles, and others in your depositories. You can download deps from githubhex.pmbitbucket, your local filesystem and many other places. Clearly erlang.mk makes Erlang vastly more versatile.

5. rebar3 

Now, if Makefiles are not your thing and you prefer to use the official build tool (since March 2016) sponsored by the Erlang/OTP team, then rebar3  is your way to go.

rebar3 is written entirely in Erlang and the idea is that you can use it without adding any Makefile to your project.

Once you install it  in your system, you should add a rebar.config file in the root folder of your project. A minimal one looks something like this (although even the options below are optional):

{deps, []}.
{erl_opts, [debug_info]}.
{cover_enabled, true}.

You can find the list of all the options you can speficy here . Then, you can run commands like the ones below in your shell:

  • $ rebar3 compile to fetch deps and build your project
  • $ rebar3 ct to run your tests
  • $ rebar3 release to generate a release

Of course, $ rebar3 help gives you the list of all available commands. And, just like erlang.mkrebar3 is also extensible through plugins .

One of the best things about rebar3 is that, by using rebar.lock, it provides repeatable builds. That way, once you're sure your project works as expected, you can be sure it will keep working as expected no matter how many times or in how many different places you compile it.


Ensuring Code Quality

I've personally stated a couple of times online (in interviews  and blog posts) how important it is (especially if you work on open-source projects) to maintain high code quality. Erlang comes with several tools that will help you with that. Erlang tools can even help you detect bugs that you'll probably find at runtime… without running your system!

image: https://i.ytimg.com/vi/8ktYyme_sUw/maxresdefault.jpg

Paddin

6. dialyzer 

Dialyzer is a static analysis tool that will help you identify type inconsistencies in your code, like when you are passing a binary() as the parameter to a function that expects a string(). This used to be a very very slow tool, but it has since been highly optimized and now runs smoothly, especially if you run it frequently. Plus, it's integrated in both rebar3  and erlang.mk . (Follow the links to learn more.)

If you use dialyzer (dia.erl), you'll see results like the one below.

  Checking whether the PLT dia.plt is up-to-date... yes
  Proceeding with analysis...
    compile    (+0.09s):   0.02s (   1 modules)
    clean      (+0.00s):   0.00s
    remote     (+0.00s):   0.18s
    order      (+0.00s):   0.00s
    typesig    (+0.12s):   0.01s (      3 SCCs)
    order      (+0.00s):   0.00s
    refine     (+0.00s):   0.01s (   1 modules)
    warning    (+0.00s):   0.00s (   1 modules)
              (+ 0.71s)

dia.erl:5: Function bad/0 has no local return
dia.erl:5: The call lists:flatten(<<_:168>>) will never return since it differs in the
            1st argument from the success typing arguments: ([any()])
 done in 0m1.16s
done (warnings were emitted)

In this case in line 5 of dia.erl, we are calling lists:flatten/1 with a 168-bit long binary (<<_:168>>) when that function expects a list ([any()]) as its parameter. This warning was not raised at compile time, but using dialyzer you can find it before it pops up during run time.

7. xref 

A much simpler tool that's been packed in the Erlang/OTP distribution is xrefxref is a cross-reference tool that analyses your code and finds calls to unexistent functions, deprecated functions and other similar things. It doesn't search as deeply as dialyzer, but it will spot obvious bugs in no time.

xref is also integrated with rebar3  and erlang.mk  (The documentation is not there yet, but it uses xref_runner  to check your code).

xref can find errors like:

…
===> Running cross reference analysis...
===> Warning: your_module:your_function/1 calls undefined function this_function:doesnt_exist/1 (Xref)
…

There xref detected that we're calling a function that doesn't exist from within the code of your_module:your_function/1. Again, that's something that the compiler will not warn you about.

8. elvis 

Besides analyzing your code in search for bugs with xref and dialyzer, you can ensure that the code in your project is maintainable. elvis is a command-line tool (and an Erlang application as well) that you can use to verify the compliance of your code to certain style rules, which you pre-define in your elvis.config file. There is a plugin for rebar3  and another one for erlang.mk . You can also use elvis online  to check your github pull requests.

Its output looks like the following:

Loading files...
Loading src/dia.erl
Applying rules...
# src/dia.erl [FAIL]
  - no_tabs
    - Line 33 has a tab at column 0.

In this case, elvis is detecting the usage of tabs for indentation which is something that's specified as invalid in the project's elvis.config file.


Debugging your Servers

The next group of tools assume that you already created your app, packed it up as a release, and deployed it to some server. They also assume that the app's been running for a while, but has started behaving strangely. So you need to debug it.

First, you connect to your server with a remote shell  (See the link for the -remsh command). Then, you use Erlang's dbg .

Alas, dbg is not a very intuitive, simple debugging tool. It's really powerful, but there are simpler tools for the task at hand. I'll show you 2 of them below.

image: https://upload.wikimedia.org/wikipedia/commons/1/13/Special_Agent_Adam_Deem_of_Air_Force_Office_of_Special_Investigation_Detachment_219.jpg

investigating…

9. redbug 

redbug is a debugging application which is quite similar to dbg, but with a more intuitive interface. It comes with eper but, to be honest, redbug is the only eper component I've ever used. With redbug, you can specify a trace pattern as a string, and it will print out a message in your console everytime a function call matching that pattern is evaluated. It looks like this:

1> redbug:start("your_module:your_private_function->return").
{156,1}
2> your_module:your_public_function().
% 19:55:12 <0.1.0>({erlang,apply,4})
% your_module:your_private_function(some, parameters)

% 19:55:12 <0.1.0>({erlang,apply,4})
% your_module:your_private_function/2 -> ok
ok
3>

I actually tend to always use the same options when starting redbug. You can check the available startup options using redbug:help(). As such, I've added this start code to my user_default  (Don't do this in production, kids!!):

redbug(What) ->
  catch redbug:stop(),
  timer:sleep(100),
  redbug:start(What, [{time, 9999999}, {msgs, 9999999}, {print_msec, true}]).

Now I can easily get redbug going.:

4> redbug("your_module:your_private_function->return").
{156,1}
5> your_module:your_public_function().
% 19:59:13 <0.1.0>({erlang,apply,4})
% your_module:your_private_function(some, parameters)

% 19:59:13 <0.1.0>({erlang,apply,4})
% your_module:your_private_function/2 -> ok
ok
6>

10. recon 

But tracing function calls is just one of the many things you can do to check the health of your Erlang servers. Fred Hebert  recollected tons of experiences dealing with that in both a great book (Stuff Goes Bad: Erlang In Anger ) and a great tool: recon .

With recon you can do many things, you can: trace function calls (just like redbug), recover the source code of your compiled modules, check app memory consumption, figure out message queue lengths, clean up binary memory, find leaks and much more. I strongly recommend you to read the book and play around with the different recon tools described in it. You'll want to know them by heart if your server starts behaving erratically.


Bonus Tracks

Now some pointers that don't really fit in the list above, but deserve to be mentioned anyway.

image: http://www.picserver.org/images/highway/phrases/bonus.jpg

Bonus

11. Meta Testing 

If you use TDD (even if you just use common test  to test your Erlang apps and you are interested in maintaining your code quality  using the tools I mentioned above, you have to check katana-test . With the code below, you'll be dialyzing, xrefing, and rocking your code every time you run your tests.

-module(your_meta_SUITE).

-include_lib("mixer/include/mixer.hrl").
-mixin([ktn_meta_SUITE]).

-export([init_per_suite/1]).

init_per_suite(Config) -> [{application, your_app} | Config].

I call that Meta Testing, and I've written two blog posts about it already. Check them out here  and here .

12. The Community

No list of great Erlang things will be complete without a shout out to the great community of developers behind it. If you're going to work on Erlang or even if you're just approaching the language and you want to know what it's all about, you have to meet the erlangers.

There are a couple of ways to acoomplish that:

  • The erlang-questions  mailing list is the most popular and arguably the official communication medium for the community. Yes, it's a mailing list. No, it will not fill up your inbox like spam.
  • We also have an IRC room  on freenode and a server  on Slack where we constantly meet.
  • And you can find some of us on ErlangCentral , too.

If you're serious about Erlang development, keep an eye on those platforms and stay connected with us for updates and other opportunities!

13. Guidelines 

Finally, I want to mention the Erlang Guidelines, published by Inaka on github . As I said in the mailing list  when we first talked about them:

[erlang_guidelines] is the set of standards that we (at Inaka) enforce in our Erlang code. […] It will only reflect the ideas of the ~8 erlangers that were/are working at Inaka. We accept contributions because we love good and constructive debate, but we don’t expect anybody […] to like [our guidelines] :)

In other words, the guidelines on that repo don't need to be your guidelines, but you should have some guidelines of your own. Forking that repo and then adapting its contents to your ideas may be a good way to start. Others have done exactly that  already. As Iñaki  once explained:

Code formatting, spacing, layout and "making the code look good" is not the goal of having guidelines. Similarly, the idea is not to engage in bondage programming in which everyone is forced to do something they don't want, but to have a baseline of order and agreed-upon-terms.

The purpose of having consensus and following it is to free up energy, not to consume it in favor of poorly-defined or subjective goals such as "it looks better". Having each one one make up his/her own rules "and damn the rest" is just as antisocial as forcing everyone to adhere to strict guidelines which dictate where you put your commas or spacing. Discipline provides freedom to the group, because once you achieve consensus on a matter, the effort of dealing with other's trespasses is greater than the effort of keeping oneself from trespassing.

Issues such as line length restrictions are a means to an end: they make the code easier to change, debug, and extend to respond faster to requirement changes. To agree with any of this, one must acknowledge that programming is a social endeavor, and group behaviour applies. It may be easier to write for you, at this time, but others will have to read it. This is the sole objective of code guidelines.


Read more at https://www.pluralsight.com/guides/erlang/10-essential-erlang-tools-for-erlang-developers#6RJgcb6IRgfYvYOZ.99
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是十个免费的Web压力测试工具: 1. Apache JMeter:这是一个功能强大的开源工具,可用于模拟多种类型的负载,并通过测试结果生成详细的分析报告。 2. LoadUI:这是一个用户友好的开源工具,可用于通过图形化界面创建和运行压力测试,并提供实时监控和分析功能。 3. Gatling:这是一个基于Scala编写的开源工具,可用于创建高度可扩展的Web应用程序性能测试脚本,并提供实时的图表和报告。 4. Locust:这是一个用Python编写的开源工具,可用于编写负载测试脚本,通过多个虚拟用户并发模拟真实场景。 5. Tsung:这是一个基于Erlang编写的开源工具,具有强大的性能和扩展性,可以模拟大量并发用户。 6. ApacheBench (ab):这是一个简单但功能强大的命令行工具,可用于发送并发请求并测量服务器的响应时间和吞吐量。 7. WebLOAD:这是一个功能全面的商业工具,提供轻松创建和运行大规模的压力测试,并提供详细的性能报告和分析。 8. Loader.io:这是一个基于云的免费工具,可快速创建和运行压力测试,通过虚拟用户模拟实际负载。 9. Siege:这是一个简单易用的命令行工具,可使用多线程并发发送请求,并提供实时性能度量。 10. Vegeta:这是一个基于Go语言开发的命令行工具,可用于生成随机负载并测量服务器的响应时间和吞吐量。 以上这些工具都可以通过其官方网站或开源社区进行下载和使用。无论您是在开发阶段还是在生产环境中测试性能,这些免费工具都是非常有帮助的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值