4

I'm writing a gen_server, which we'll just call gen_server_db, with nothing too terribly special about it. There is a possibility that a library it uses (emysql) will experience a connection failure while trying to find a database server (in gen_server_db:init()). When I catch the exception and try to print something to the console, I get zip. Neither of the io:format messages, in the code sample below, ever find their way to the console. I seem to recall hearing a reason for this, long ago, but I can't recall why.

init(Args) ->
    % I've condensed the way I actually get this stuff to one line, but if I have a
    % database online I connect properly, so I know that I'm getting the Host, User, etc.  
    {Host, User, Password, DB, PoolSize} = application:get_env(gen_server_db, config),

    init_mysql_connection(gen_server_db_pool, PoolSize, User, Password, Host, DB),

    % When the net connection to the db is down, I never get here.
    ok.

init_mysql_connection(bgo_db_pool, PoolSize, User, Password, Host, DB) ->
    try
        emysql:add_pool(bgo_db_pool, PoolSize, User, Password, Host, 3306, DB, utf8)
    catch
        exit:failed_to_connect_to_database ->
            io:format("Cannot connect to the mysql database server.  Retrying in 1 sec.~n"),
            timer:sleep(1000),
            init_mysql_connection(bgo_db_pool, PoolSize, User, Password, Host, DB);
        Error:Reason ->
            io:format("Database connection error: ~p:~p~n", [Error, Reason]),
            1/0
    end.
Sniggerfardimungus
  • 11,583
  • 10
  • 52
  • 97
  • It doesn't look like group leader redirection is happening, so one possible reason for not seeing any output is that the code doesn't actually make it that far. Have you tried calling io:format() as the first thing in init(Args) to convince yourself that your init code runs at all? Also, try starting SASL to get crash reports when a gen_server dies. – RichardC Apr 27 '12 at 21:30

2 Answers2

4

All I/O sent through io:format is sent to the current group_leader of the process being run. It is then this processes responsibility to print the message using io:fwrite.

If you just want to dump some debug info while coding you can use erlang:display/1

Lukas
  • 5,182
  • 26
  • 17
  • In the end, I used global:register_name(io_format_target, group_leader()) on the console, and io:format(global:whereis_name(io_format_target), "foo~p~n", [bar]). – Sniggerfardimungus Aug 09 '12 at 18:59
0

I recommend you to use error_logger module instead of io:format. io:format outputs the message to tty console, a standard output. If your gen_server is started by a console, you will see those message, but, if your server is started as a detached mode, you will never see those messages.

This is a manual and you need to have SASL started.

http://www.erlang.org/doc/man/error_logger.html

and inside your config file, you need to define output file for this log.

....
{sasl, [{sasl_error_logger, {file,"/tmp/sasl_error.log"}},{errlog_type, all}]}
....
allenhwkim
  • 27,270
  • 18
  • 89
  • 122