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

Prometheus support #4238

Merged
merged 1 commit into from
Jul 2, 2024
Merged

Prometheus support #4238

merged 1 commit into from
Jul 2, 2024

Conversation

pouriya
Copy link
Contributor

@pouriya pouriya commented Jun 25, 2024

Example config

# ...
  -
    port: 5280
    ip: "::"
    module: ejabberd_http
    request_handlers:
      /metrics: mod_prometheus
# ...

modules:
  # ...
    mod_prometheus:
    mnesia: true
    vm:
      memory: true
      system_info: true
      statistics: false
      distribution: false
      microstate_accounting: false
    hooks:
      # Histogram for a hook:
      - hook: user_send_packet
        type: histogram
        help: "Handling of sent messages duration in millisecond"
        stanza_label: true
        host_label: true
      # Counter for a hook:
      - hook: user_send_packet
        type: counter
        help: "Number of sent messages"
      #Histograms only for some callbacks of a hook:
      - hook: user_send_packet
        type: histogram
        host_label: true
        collect:
          - module: mod_carboncopy
            function: user_send_packet
            help: "Handling of carbon copied messages in millisecond"
          - module: mod_mam
            function: user_send_packet
            help: "Handling of MAM messages in millisecond"
            buckets:
              - 10
              - 100
              - 750
              - 1000
              - 1500

Output example (After sending some messages)

curl http://127.0.0.1:5280/metrics
...
# TYPE user_send_packet_mod_mam_duration_milliseconds histogram
# HELP user_send_packet_mod_mam_duration_milliseconds Handling of MAM messages in millisecond
user_send_packet_mod_mam_duration_milliseconds_bucket{host="localhost",le="10"} 43
user_send_packet_mod_mam_duration_milliseconds_bucket{host="localhost",le="100"} 43
user_send_packet_mod_mam_duration_milliseconds_bucket{host="localhost",le="750"} 43
user_send_packet_mod_mam_duration_milliseconds_bucket{host="localhost",le="1000"} 43
user_send_packet_mod_mam_duration_milliseconds_bucket{host="localhost",le="1500"} 43
user_send_packet_mod_mam_duration_milliseconds_bucket{host="localhost",le="+Inf"} 43
user_send_packet_mod_mam_duration_milliseconds_count{host="localhost"} 43
user_send_packet_mod_mam_duration_milliseconds_sum{host="localhost"} 9.0e-6
# TYPE user_send_packet_mod_carboncopy_duration_milliseconds histogram
# HELP user_send_packet_mod_carboncopy_duration_milliseconds Handling of carbon copied messages in millisecond
user_send_packet_mod_carboncopy_duration_milliseconds_bucket{host="localhost",le="1"} 43
user_send_packet_mod_carboncopy_duration_milliseconds_bucket{host="localhost",le="10"} 43
user_send_packet_mod_carboncopy_duration_milliseconds_bucket{host="localhost",le="100"} 43
user_send_packet_mod_carboncopy_duration_milliseconds_bucket{host="localhost",le="500"} 43
user_send_packet_mod_carboncopy_duration_milliseconds_bucket{host="localhost",le="750"} 43
user_send_packet_mod_carboncopy_duration_milliseconds_bucket{host="localhost",le="1000"} 43
user_send_packet_mod_carboncopy_duration_milliseconds_bucket{host="localhost",le="3000"} 43
user_send_packet_mod_carboncopy_duration_milliseconds_bucket{host="localhost",le="5000"} 43
user_send_packet_mod_carboncopy_duration_milliseconds_bucket{host="localhost",le="+Inf"} 43
user_send_packet_mod_carboncopy_duration_milliseconds_count{host="localhost"} 43
user_send_packet_mod_carboncopy_duration_milliseconds_sum{host="localhost"} 3.0e-6
# TYPE user_send_packet_duration_milliseconds histogram
# HELP user_send_packet_duration_milliseconds Handling of sent messages duration in millisecond
user_send_packet_duration_milliseconds_bucket{stanza="presence",host="localhost",le="1"} 1
user_send_packet_duration_milliseconds_bucket{stanza="presence",host="localhost",le="10"} 1
user_send_packet_duration_milliseconds_bucket{stanza="presence",host="localhost",le="100"} 1
user_send_packet_duration_milliseconds_bucket{stanza="presence",host="localhost",le="500"} 1
user_send_packet_duration_milliseconds_bucket{stanza="presence",host="localhost",le="750"} 1
user_send_packet_duration_milliseconds_bucket{stanza="presence",host="localhost",le="1000"} 1
user_send_packet_duration_milliseconds_bucket{stanza="presence",host="localhost",le="3000"} 1
user_send_packet_duration_milliseconds_bucket{stanza="presence",host="localhost",le="5000"} 1
user_send_packet_duration_milliseconds_bucket{stanza="presence",host="localhost",le="+Inf"} 1
user_send_packet_duration_milliseconds_count{stanza="presence",host="localhost"} 1
user_send_packet_duration_milliseconds_sum{stanza="presence",host="localhost"} 0.0
user_send_packet_duration_milliseconds_bucket{stanza="message",host="localhost",le="1"} 35
user_send_packet_duration_milliseconds_bucket{stanza="message",host="localhost",le="10"} 35
user_send_packet_duration_milliseconds_bucket{stanza="message",host="localhost",le="100"} 35
user_send_packet_duration_milliseconds_bucket{stanza="message",host="localhost",le="500"} 35
user_send_packet_duration_milliseconds_bucket{stanza="message",host="localhost",le="750"} 35
user_send_packet_duration_milliseconds_bucket{stanza="message",host="localhost",le="1000"} 35
user_send_packet_duration_milliseconds_bucket{stanza="message",host="localhost",le="3000"} 35
user_send_packet_duration_milliseconds_bucket{stanza="message",host="localhost",le="5000"} 35
user_send_packet_duration_milliseconds_bucket{stanza="message",host="localhost",le="+Inf"} 35
user_send_packet_duration_milliseconds_count{stanza="message",host="localhost"} 35
user_send_packet_duration_milliseconds_sum{stanza="message",host="localhost"} 1.3e-5
user_send_packet_duration_milliseconds_bucket{stanza="iq",host="localhost",le="1"} 7
user_send_packet_duration_milliseconds_bucket{stanza="iq",host="localhost",le="10"} 7
user_send_packet_duration_milliseconds_bucket{stanza="iq",host="localhost",le="100"} 7
user_send_packet_duration_milliseconds_bucket{stanza="iq",host="localhost",le="500"} 7
user_send_packet_duration_milliseconds_bucket{stanza="iq",host="localhost",le="750"} 7
user_send_packet_duration_milliseconds_bucket{stanza="iq",host="localhost",le="1000"} 7
user_send_packet_duration_milliseconds_bucket{stanza="iq",host="localhost",le="3000"} 7
user_send_packet_duration_milliseconds_bucket{stanza="iq",host="localhost",le="5000"} 7
user_send_packet_duration_milliseconds_bucket{stanza="iq",host="localhost",le="+Inf"} 7
user_send_packet_duration_milliseconds_count{stanza="iq",host="localhost"} 7
user_send_packet_duration_milliseconds_sum{stanza="iq",host="localhost"} 0.0
# TYPE user_send_packet_total counter
# HELP user_send_packet_total Number of sent messages
user_send_packet_total 43

Prometheus screenshot

Screenshot 2024-06-25 at 22-13-07 Prometheus Time Series Collection and Processing Server

@badlop badlop self-assigned this Jun 25, 2024
@pouriya
Copy link
Contributor Author

pouriya commented Jun 26, 2024

I will fix dialyzer etc after review.

@pouriya
Copy link
Contributor Author

pouriya commented Jun 28, 2024

I'm going to change subscriber API and leave run and run_fold untouched.

@prefiks
Copy link
Member

prefiks commented Jun 28, 2024

I think you could even not need any changes in ejabberd_hooks, you will need to add two hooks with low and high priority, to get notified at start and of hook, ejabberd_hooks:add/remove accept closures, so you could generate required function on demand. Your function can return 'EXIT' atom to make output from it be ignored. Only issue will be arrity of those function, as you will not receive hook arguments as list, but as multiple arguments in those functions.

@pouriya
Copy link
Contributor Author

pouriya commented Jun 28, 2024

you will need to add two hooks with low and high priority, to get notified at start and of hook.

@prefiks Yes. But what if we disable the module (M:F) we're monitoring? There is no way to know that ejabberd_hooks called or did not call specific module M:F. With these changes, If a hook has subscriber(s) they will know exactly what M:F ejabberd_hooks runs.

@pouriya
Copy link
Contributor Author

pouriya commented Jun 28, 2024

I force pushed changes and left original run and run_fold untouched.

@pouriya
Copy link
Contributor Author

pouriya commented Jun 28, 2024

We could also have a configuration parameter to set module parameters as labels. for example:

modules:
  # ...
    mod_prometheus:
    hooks:
      # Histogram for a hook:
      - hook: user_send_packet
        type: histogram
        help: "Handling of sent messages duration in millisecond"
        collect: modules   # HERE

Output:

...
user_send_packet_duration_milliseconds_bucket{module="mod_mam",le="10"} 43
user_send_packet_duration_milliseconds_bucket{module="mod_carboncopy",le="10"} 43
user_send_packet_duration_milliseconds_bucket{module="mod_foo",le="10"} 43
user_send_packet_duration_milliseconds_bucket{module="mod_bar",le="10"} 43
...

Any idea?

@pouriya
Copy link
Contributor Author

pouriya commented Jun 28, 2024

Seems like don't have Dialyzer issue anymore :-)

@Neustradamus
Copy link
Contributor

@pouriya: Nice PR, good job with ejabberd team!

@mremond
Copy link
Member

mremond commented Jul 1, 2024

I think this should be added to ejabberd-contribs repository: https://github.com/processone/ejabberd-contrib

@pouriya
Copy link
Contributor Author

pouriya commented Jul 1, 2024

@mremond

I think this should be added to ejabberd-contribs

  1. We need hook's subscriber API for this module.
  2. We need rebar3 to compile prometheus & its deps. Is it possible to add it ejabberd-contrib and compile it via rebar3? I think ejabberd compiles them directly via compiler app.

@badlop
Copy link
Member

badlop commented Jul 1, 2024

Yes :) I have almost ready the fixes in ejabberd that will allow this:

  • add support for hooks subscriptions to ejabberd
  • add mod_prometheus to ejabberd-contrib, with support to get the dependencies, install and start
  • add some basic documentation to start using the module

I'll complete testing tomorrow and show how to accomplish it.

@pouriya
Copy link
Contributor Author

pouriya commented Jul 1, 2024

@badlop @mremond
So we're ready to merge hook subscriber commit here. Am I right?

@badlop
Copy link
Member

badlop commented Jul 1, 2024

So we're ready to merge hook subscriber commit here. Am I right?

Mostly yes :) Do you still have some improvement or fix planned for ejabberd_hooks.erl ?

@pouriya
Copy link
Contributor Author

pouriya commented Jul 1, 2024

@badlop
I don't think so...
I'll see what can be done before force push. on it.

@pouriya
Copy link
Contributor Author

pouriya commented Jul 1, 2024

@badlop force pushed just ejabberd_hooks changes. When we're ready to accept Prometheus in ejabberd-contrib?

@coveralls
Copy link

Coverage Status

coverage: 32.064% (-0.07%) from 32.13%
when pulling e5ed0bc on pouriya:prometheus
into 3124644 on processone:master.

@badlop badlop merged commit 82d95ac into processone:master Jul 2, 2024
7 checks passed
@badlop
Copy link
Member

badlop commented Jul 2, 2024

I've merged this PR with the "hooks subscription" feature.

And I've added a new directory in ejabberd-contrib with everything prepared for your mod_prometheus:
https://github.com/processone/ejabberd-contrib/tree/master/mod_prometheus

Now you can create a directory src/ there, copy your *.erl files, fix anything you want in the documentation, example files... and submit a PR

@pouriya
Copy link
Contributor Author

pouriya commented Jul 2, 2024

@badlop Thanks!

@badlop badlop modified the milestones: ejabberd 24.xx, ejabberd 24.07 Jul 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants