Browse Source

Merge pull request #226 from enidgjoleka/use-application-name-when-establishing-a-connection

Use application name when establishing a connection
Sergey Prokhorov 5 years ago
parent
commit
d8ca6d4d94
4 changed files with 28 additions and 3 deletions
  1. 3 0
      README.md
  2. 7 1
      src/commands/epgsql_cmd_connect.erl
  3. 5 2
      src/epgsql.erl
  4. 13 0
      test/epgsql_SUITE.erl

+ 3 - 0
README.md

@@ -112,6 +112,9 @@ Only `host` and `username` are mandatory, but most likely you would need `databa
    Default is `[null, undefined]`, i.e. encode `null` or `undefined` in parameters as `NULL`
    Default is `[null, undefined]`, i.e. encode `null` or `undefined` in parameters as `NULL`
    and decode `NULL`s as atom `null`.
    and decode `NULL`s as atom `null`.
 - `replication` see [Streaming replication protocol](#streaming-replication-protocol)
 - `replication` see [Streaming replication protocol](#streaming-replication-protocol)
+- `application_name` is an optional string parameter. It is usually set by an application upon
+   connection to the server. The name will be displayed in the `pg_stat_activity`
+   view and included in CSV log entries.
 
 
 Options may be passed as proplist or as map with the same key names.
 Options may be passed as proplist or as map with the same key names.
 
 

+ 7 - 1
src/commands/epgsql_cmd_connect.erl

@@ -89,7 +89,13 @@ client_handshake(Sock, PgSock, #connect{opts = #{username := Username} = Opts} =
                          epgsql_sock:init_replication_state(PgSock1)};
                          epgsql_sock:init_replication_state(PgSock1)};
                     _ -> {Opts3, PgSock1}
                     _ -> {Opts3, PgSock1}
                 end,
                 end,
-            ok = epgsql_sock:send(PgSock2, [<<196608:?int32>>, Opts4, 0]),
+            Opts5 = case Opts of
+                        #{application_name := ApplicationName}  ->
+                            [Opts3 | ["application_name", 0, ApplicationName, 0]];
+                        _ ->
+                            Opts4
+                    end,
+            ok = epgsql_sock:send(PgSock2, [<<196608:?int32>>, Opts5, 0]),
             PgSock3 = case Opts of
             PgSock3 = case Opts of
                           #{async := Async} ->
                           #{async := Async} ->
                               epgsql_sock:set_attr(async, Async, PgSock2);
                               epgsql_sock:set_attr(async, Async, PgSock2);

+ 5 - 2
src/epgsql.erl

@@ -62,7 +62,8 @@
     {async,    Receiver   :: pid() | atom()}       | % process to receive LISTEN/NOTIFY msgs
     {async,    Receiver   :: pid() | atom()}       | % process to receive LISTEN/NOTIFY msgs
     {codecs,   Codecs     :: [{epgsql_codec:codec_mod(), any()}]} |
     {codecs,   Codecs     :: [{epgsql_codec:codec_mod(), any()}]} |
     {nulls,    Nulls      :: [any(), ...]} |    % terms to be used as NULL
     {nulls,    Nulls      :: [any(), ...]} |    % terms to be used as NULL
-    {replication, Replication :: string()}. % Pass "database" to connect in replication mode
+    {replication, Replication :: string()} | % Pass "database" to connect in replication mode
+    {application_name, ApplicationName :: string()}.
 
 
 -type connect_opts() ::
 -type connect_opts() ::
         [connect_option()]
         [connect_option()]
@@ -77,7 +78,9 @@
           async => pid() | atom(),
           async => pid() | atom(),
           codecs => [{epgsql_codec:codec_mod(), any()}],
           codecs => [{epgsql_codec:codec_mod(), any()}],
           nulls => [any(), ...],
           nulls => [any(), ...],
-          replication => string()}.
+          replication => string(),
+          application_name => string()
+          }.
 
 
 -type connect_error() :: epgsql_cmd_connect:connect_error().
 -type connect_error() :: epgsql_cmd_connect:connect_error().
 -type query_error() :: #error{}.              % Error report generated by server
 -type query_error() :: #error{}.              % Error report generated by server

+ 13 - 0
test/epgsql_SUITE.erl

@@ -34,6 +34,7 @@ groups() ->
     Groups = [
     Groups = [
         {connect, [parrallel], [
         {connect, [parrallel], [
             connect,
             connect,
+            connect_with_application_name,
             connect_to_db,
             connect_to_db,
             connect_as,
             connect_as,
             connect_with_cleartext,
             connect_with_cleartext,
@@ -179,6 +180,18 @@ uuid_to_bin_string(<<U0:32, U1:16, U2:16, U3:16, U4:48>>) ->
 connect(Config) ->
 connect(Config) ->
     epgsql_ct:connect_only(Config, []).
     epgsql_ct:connect_only(Config, []).
 
 
+connect_with_application_name(Config) ->
+    Module = ?config(module, Config),
+    Fun = fun(C) ->
+              Query = "select application_name from pg_stat_activity",
+              {ok, _Columns, Rows} = Module:equery(C, Query),
+              ?assert(lists:member({<<"app_test">>}, Rows))
+          end,
+    epgsql_ct:with_connection(Config,
+                              Fun,
+                              "epgsql_test",
+                              [{application_name, "app_test"}]).
+
 connect_to_db(Connect) ->
 connect_to_db(Connect) ->
     epgsql_ct:connect_only(Connect, [{database, "epgsql_test_db1"}]).
     epgsql_ct:connect_only(Connect, [{database, "epgsql_test_db1"}]).