Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add docs about using lager in elixir [JIRA: RIAK-2495] #348

Closed
jadeallenx opened this issue Apr 9, 2016 · 12 comments
Closed

Add docs about using lager in elixir [JIRA: RIAK-2495] #348

jadeallenx opened this issue Apr 9, 2016 · 12 comments

Comments

@jadeallenx
Copy link
Member

We should include in the readme a section about using lager in the context of elixir apps or logging abstraction libs like hut

@Basho-JIRA Basho-JIRA changed the title Add docs about using lager in elixir Add docs about using lager in elixir [JIRA: RIAK-2495] Apr 9, 2016
@zhaohansprt
Copy link

then how it goes?

@zhaohansprt
Copy link

i found there is the way to call lager in elixir but seemed not like in erlang
:lager.log(:error, self(), "message ~p",[:erlang.node()])

@jadeallenx
Copy link
Member Author

Hi - I don't think anyone who works on lager day-to-day has the necessary experience with elixir to write a documentation section like this. But we would welcome someone who does to help with that section of the docs.

That's why I tagged this issue as "help wanted"

@holsee
Copy link
Contributor

holsee commented Mar 7, 2017

I'll give this a shot. A few things worth figuring out first...

I would say as an elixir dev there would be a few options that come to mind when including lager in a project.

I would be asking myself:

  • "Is there a wrapper that would allow for compile time macro benefits for log level exclusion?"
    (possibly not knowing that this can is done with parse transforms in lager)

  • "is my logging going to become a risk / be impacted through using the elixir Logger abstraction with lager backend?" i.e. are the positives of lager going to be impacted / lost?

Questions like this would be great to have an answer for, to help potential consumers decide which way to go an when.

So the first thing to think about would be to figure out if I wished to use lager as a Logger backend, or directly. If I opt for directly, I would then decide if I wanted to use a wrapper weighing up the usual pros and cons of doing such a thing.

Option 1: The Elixir Logging abstraction (with a lager backend)

see: https://hexdocs.pm/logger/Logger.html#module-backends

The elixir Logger is pretty nice, and allows for "backends" to be plugged in, whilst providing a nice idiomatic logging api. Other benefits of this approach come from the elixir macro system which enables caller introspection and the logging calls to be stripped out during compile time for the logging levels that the application doesn't wish to include for a given build type.

From what I remember backends are super simple to plug in, back pressure is handled quite nicely and the adapter is supervised in a standard OTP fashion.

I would for sure be opting for this approach myself if I was, say, writing a library for redistribution in elixir so the logging strategy of choice can be plugged in. On the same note many elixir libs that I may be pulling in would also use the elixir Logger, so this scenario is certainly going to be common and should probably be mentioned.

Now wether or not lager contributors wish to provide a reference implementation is open to discussion.

Option 2: Using lager directly

Elixir modules are the same as Erlang, both are actually atoms under the hood, just Elixir provides a explicit Pascal Case module syntax that hides the fact that under the hood it is an atom prefixed with Elixir..

So as @zhaohansprt mentions, when calling Erlang from elixir it looks as follows:

iex(1)> :erlang.module_info()
[module: :erlang,
 exports: [bitsize: 1, check_process_code: 2, check_process_code: 3,
  garbage_collect: 1, garbage_collect: 2, garbage_collect_message_area: 0,
...

Option 3: Provide an Elixir Wrapper

It is not uncommon to see Elixir wrappers around Erlang libraries e.g. https://github.com/meh/amnesia

You can then tell the compiler to inline the body of the call, removing any penalty for the elixir wrapper being in place.

@compile {:inline, myfun: 1}

When you inline a function, its calls will be replaced with the function body itself at compile time. This can be used to squeeze the last bit of performance out of a specific function call, eliminating the overhead of one single function call.

As mentioned previously the elixir modules, with the same name as the Erlang modules would not clash due to the Elixir. prefix that is implicitly added under the hood.

Elixir App Config style

Another consideration regarding docs would be an Elixir specific configuration guide given the syntax elixir has for proplists and the config macro:

# config/config.exs
config :lager,
  log_root: '/var/log/hello',
  handlers: [
    lager_console_backend: :info,
    lager_file_backend: [file: "error.log", level: :error],
    lager_file_backend: [file: "console.log", level: :info]
  ]

What everyone really wants: The Quick Start :)

The most basic thing would be the quick start that would show how to add lager as a dependency properly something like:

# mix.exs
def application do
  [
    applications: [:lager],
    erl_opts: [parse_transform: "lager_transform"]
  ]
end

defp deps do
  [{:lager, github: "erlang-lager/lager"}]
end
  • and the config.exs as shown above.

Hope that is helpful, giving a little insight to an elixir devs point of view. I will start to put something together and it can be tweaked as needs be.

@jadeallenx
Copy link
Member Author

Wow, lovely @holsee. Would be great to get this in a PR :)

@jadeallenx
Copy link
Member Author

Any further progress on this?

@holsee
Copy link
Contributor

holsee commented Mar 16, 2017

@mrallen1 it has been on my todo list, not been forgotten 👍 . I just wanted to verify that the parse transforms and the api in the comment was working ok and that was taking a little more time that I have had free recently.

I plan to mimic the Erlang snippets with the elixir versions and add a section for "elixir considerations" that dumps some of the pertinent info from my last comment.

Tis St Patrick's tomorrow ☘️ but I am sure I could get a PR in tomorrow morning if not in by later this evening if all goes to plan.

@holsee
Copy link
Contributor

holsee commented Mar 16, 2017

Dang!

elixir-lang/elixir#5762 Deprecate usage of parse_transforms

https://github.com/elixir-lang/elixir/blob/master/lib/elixir/lib/module.ex#L1064

# TODO: Remove on Elixir v2.0
case value do
  {:parse_transform, _} when key == :compile and is_list(stack) ->
    IO.warn "@compile {:parse_transform, _} is deprecated. " <>
            "Elixir will no longer support Erlang-based transforms in future versions", stack
  _ ->
    :ok
end

Reaching out to the core team to see what's up, as we wont want to recommend using parse transforms if this is going to be removed from the language!

This isn't a show stopper for lager use in elixir, as a shim would still allow for the same functionality via elixir's macros, but that would have to be another project.

@fishcakez
Copy link
Contributor

@holsee I believe some additional config/advise will be required to prevent lager and logger squabbling over error_logger handlers. I have not used logger since the 2.* so might be incorrect about this.

@holsee
Copy link
Contributor

holsee commented Mar 17, 2017

I am wondering if we even document anything for elixir at this point, as a related elixir_lagger project with the wrapper seems in order. We could however put something in lager README for now to help folks out, I have a good idea of what to put in to help people get started.

@fishcakez can you be specific please, code example? Not familiar with this issue.

@fishcakez
Copy link
Contributor

@holsee a lager -> logger forwarded had this config to prevent lager removing the logger handler: https://github.com/PSPDFKit-labs/lager_logger/blob/master/config/config.exs#L7. Note that parse transforms are not going to stop working for quite a while. The deprecation is there to give people ample time to move away from them so that Elixir is not bound to Erlang AST in the long term.

@jadeallenx
Copy link
Member Author

OK, I merged #398 so I'm going to close this issue. Thanks @holsee for the writing and @fishcakez for your comments and review!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants