Sqlcommenter (sqlcommenter v0.2.0-beta.1)

Sqlcommenter is a library for adding sqlcommener comments to your ecto queries.

## Usage Add these callbacks to your Repo module, adjust to your needs. The stacktrace option is only required when you plan to include use the extractrepocaller function. This function also accepts the __MODULE as the second argument to exclude it from the stacktrace.

The sqlcommenter option is used for adding static data to the commenent like the running app, team, owner etc. Any dynamic data can be added in the prepare_query function. Besides the caller it can also add the trace and span.

The generated comment needs to be added as comment option - this will be passed to the adapter.


def default_options(_operation) do
  [stacktrace: true, prepare: :unnamed, sqlcommenter: [team: "sqlcomm", app: "sqlcomm"]]
end

def prepare_query(_operation, query, opts) do
  sqlcommennter_defaults = Keyword.get(opts, :sqlcommenter)
  caller = Sqlcommenter.extract_repo_caller(opts, __MODULE__)
  comment = Sqlcommenter.to_str([caller: caller] ++ sqlcommenter_defaults)

  {query, [comment: comment] ++ opts}
end

Now your postgres logs should look will return a log line like this:

2024-10-27 21:43:04.331 GMT,"postgres","sqlcomm_test",416336,"127.0.0.1:53348",671eb3e8.65a50,6,
"SELECT",2024-10-27 21:43:04 GMT,15/54,61620,LOG,00000,"execute <unnamed>: SELECT u0.""id"",
u0.""active"", u0.""name"", u0.""inserted_at"", u0.""updated_at"" FROM ""users"" AS
u0/*app='sqlcomm',caller='Elixir.SqlcommTest.test%20insert%20user%2F1',team='sqlcomm'*/"
,,,,,,,,,"","client backend",,0

Summary

Functions

Appends serialized data to query

Appends serialized data to query

extracts serialized data from query

The same as to_iodata but it assumes the keys are sorted already.

Encodes enumerable to iodata iex> Sqlcommenter.to_iodata(controller: :person, function: :index) [

Encodes enumerable to string iex> Sqlcommenter.to_str(controller: :person, function: :index) "controller='person',function='index'"

Functions

Link to this function

append_to_io_query(query, params)

@spec append_to_io_query(iodata(), Keyword.t()) :: iodata()

Appends serialized data to query

iex> query = ["SELECT", [~s{p0."id"}, ", ", ~s{p0."first_name"}], " FROM ", ~s{"person"."person"}, " AS ", "p0"] iex> Sqlcommenter.append_to_io_query(query, %{controller: :person, function: :index}) [ ["SELECT", [~s{p0."id"}, ", ", ~s{p0."first_name"}], " FROM ", ~s{"person"."person"}, " AS ", "p0"], " /*", [

["controller", "='", "person", "'"],
",",
["function", "='", "index", "'"]

], "*/"]

Link to this function

append_to_query(query, params)

@spec append_to_query(String.t(), Keyword.t()) :: String.t()

Appends serialized data to query

iex> query = ~s{SELECT p0."id", p0."first_name" FROM "person"."person" AS p0} iex> Sqlcommenter.append_to_query(query, %{controller: :person, function: :index}) ~s{SELECT p0."id", p0."first_name" FROM "person"."person" AS p0 } <> "/controller='person',function='index'/"

Link to this function

deserialize(query)

@spec deserialize(String.t()) :: map()

extracts serialized data from query

Example

iex> query = ~s{SELECT p0."id", p0."first_name" FROM "person"."person" AS p0 /request_id='fa2af7b2-d8e1-4e8f-8820-3fd648b73187'/} iex> Sqlcommenter.deserialize(query) %{"request_id" => "fa2af7b2-d8e1-4e8f-8820-3fd648b73187"}

Link to this function

extract_repo_caller(opts, repo_module)

Link to this function

sorted_to_iodata(params)

@spec sorted_to_iodata(Keyword.t()) :: iodata()

The same as to_iodata but it assumes the keys are sorted already.

Link to this function

to_iodata(params)

@spec to_iodata(Keyword.t()) :: maybe_improper_list()

Encodes enumerable to iodata iex> Sqlcommenter.to_iodata(controller: :person, function: :index) [

["controller", "='", "person", "'"],
",",
["function", "='", "index", "'"]

]

@spec to_str(Keyword.t()) :: String.t()

Encodes enumerable to string iex> Sqlcommenter.to_str(controller: :person, function: :index) "controller='person',function='index'"