Product usage analytics coming to Checkmk 2.3, 2.4, and 2.5

Hello Checkmk users!

At Checkmk, we constantly strive to improve in the areas most important to your daily work. We want to be able to provide you with the best monitoring possible for your use cases, so that you can spot and resolve problems proactively and ensure your IT infrastructure stays healthy. For that, we need to understand how you use Checkmk and what are your most essential monitoring use cases. We have different sources of input to understand such topics. However, while data from the Ideas Portal, interviews, and surveys are crucial, they sometimes leave us with blind spots.

To better understand your monitoring needs, we will be introducing Product usage analytics in Checkmk 2.5. It will also be made available in 2.4 and 2.3 with the patch release following the 2.5 release. When activated, this feature will collect usage data about Checkmk and thus provide us better insights into how you monitor your infrastructure and applications.

This feature will be off by default in all on-premise editions, and we would like to ask you to enable it if possible. The benefit for you is a better-informed product roadmap, resulting in a Checkmk that is more closely aligned with your real-world monitoring requirements.
We will not gather any personal or sensitive information, such as IP addresses, site names, licence information, service names, host names, or folder names. Still, before enabling this, we recommend reviewing all the data and scope of affected instances.

This is a quick heads-up regarding what’s coming soon to Checkmk. We will update this thread with an official Werk once product usage analytics is officially planned in a patch release. We are currently preparing the documentation and technical details to remain fully transparent about how we collect and transfer telemetry data. We hope for your cooperation in helping us understand how Checkmk is used.

If you have any questions, please reach out—we’re happy to answer.

2 Likes

In case you are interested in what is being collected, here is an example:

OMD[heute]:~$ cmk-product-usage 
{
  "metadata": {
    "version": "v1",
    "namespace": "checkmk",
    "name": "product_usage_analytics"
  },
  "data": {
    "id": "139183b7-cd1b-4f88-ad89-5961e467f1b6",
    "count_hosts": 6,
    "count_services": 156,
    "count_folders": 4,
    "edition": "ultimate",
    "cmk_version": "2.5.0-2026.02.23",
    "timestamp": 1771852850,
    "checks": {
      "check-mk": {
        "count": 6,
        "count_hosts": 6,
        "count_disabled": 0
      },
      "check_mk-uptime": {
        "count": 4,
        "count_hosts": 4,
        "count_disabled": 0
      },
      "check_mk-tplink_poe": {
        "count": 12,
        "count_hosts": 2,
        "count_disabled": 0
      },
      "check_mk-interfaces": {
        "count": 35,
        "count_hosts": 3,
        "count_disabled": 0
      },
      "check-mk-inventory": {
        "count": 6,
        "count_hosts": 6,
        "count_disabled": 0
      },
      "check_mk-memory_utilization": {
        "count": 3,
        "count_hosts": 3,
        "count_disabled": 0
      },
      "check_mk_active-cmk_inv": {
        "count": 6,
        "count_hosts": 6,
        "count_disabled": 0
      },
      "check_mk-snmp_info": {
        "count": 3,
        "count_hosts": 3,
        "count_disabled": 0
      },

EDIT: Adapted the command line command to match a recent rename. The script which collects the data can already be run on a 2.5 build.

5 Likes

A question about the check names. Judging from the data I guess that those are names of the built-in plugins. Will names of third-party plugins be transmitted, too? The reason I’m asking is that we write a certain amount of customer-specific checks, and those contain our customers’ names and even some potentially proprietary service names in the plugin names. I’d have to get their OK first.

3 Likes

I believe that some other useful data could be exported like the amount of innefective rules or even the usage of checkers and helpers. This could be used to suggest configuration changes (Advisor) and potentially reduce support tickets. This could be used as an argument to allow that data collection to happen.

Hi,
technically, we run a livestatus query to get the check command and then strip everything after the !, so that we get only the name of check. See the following example. This way we remove sensitive information. We don’t care which websites you check, in this case we rather want to know what checks are being used, so that we know where to invest further into.

check_mk_active-httpv2!–url https://checkmk.com → check_mk_active-httpv2

As we also want to use this as a basis for mainlining decisions, we do not differentiate between shipped and non-shipped (livestatus neither does so as well anyway). It helps us to know which exchange plug-ins are actually heavily used, and which we should prioritize in mainlining next.
You can run the command within the site and see if there is anything confidential in it, e.g. if the check name is too revealing (check name != service description as we on purpose do not collect the service item which can definitely have revealing information). And then you can decide if you want to opt-in and donate your data, or not.

@paulosantanabr Let’s see where the journey goes - but we decided we only collect data for which we have a clear purpose and already questions as of today. While I personally love to have as much data as possible, we can make better decisions only with diverse data, from many different users. And we believe minimal collection favours this

EDIT: Added explanation for the stripping of parameters from e.g. active checks

6 Likes

Thanks for the explanation. I don’t think I’ll opt-in, then. I don’t want to have to make that decision for the 80 or so sites we have, that’s too much effort.

I’m aware that check (plugin) names don’t equal service names. My argument was that the customer & service-specific checks that we write often contain the name of the thing we’re monitoring, and that might be part of a proprietary/non-public project, therefore we cannot simply expose even the plugin names to third-parties like that.

Maybe let us exclude data from certain plugins from the statistics, e.g. filter via an exclusion regex, managed from the central site. That’d be trivial enough for us to manage and would make opt-in highly likely. Something to think about.

5 Likes

Hey Moritz, thought about the same thing. Should be rather straight-forward to implement in the script - just have to think where we expose that (probably via a global setting). Will forward to the respective team.

4 Likes

As promised, here is the werk: https://checkmk.com/werk/19605

Product usage analytics is shipped starting from 2.5.0b3, 2.4.0p26, 2.3.0p47 and disabled by default in our self-hosted solutions.

Here is the user guide article with further details: Product usage analytics

Also, have a look at the product usage analytics manifest

2 Likes

Maybe you could explain why the columns “Check command” and “Check command expanded” display the same values.

Example:
Service: HTTPS checkmk.com
Check command: check_mk_active-httpv2!–url https://checkmk.com
Check command expanded: check_mk_active-httpv2!–url https://checkmk.com

I would have expected that the first column shows only the command itself, while the second includes the command with its arguments:

Check command: check_mk_active-httpv2
Check command expanded: check_mk_active-httpv2!–url https://checkmk.com

Then both you and we could use the “Check command” column in views and Livestatus queries to retrieve the check command without any arguments. :wink:

You might want to consider collecting the data centrally and in a consolidated way in the Ultimate Multi-Tenancy Edition. Nobody wants to set up firewall or proxy rules for 500 sites, and in many companies systems are not allowed to send data directly to the Internet.

An offline mode – similar to the licensing process – would therefore be very helpful, enabling you to also receive data from larger environments.

5 Likes

If I remember correctly, then Check command expanded resolves macro.
check_mk_active-httpv2!–url https://$HOSTNAME$
vs.
check_mk_active-httpv2!–url https://checkmk.com

2 Likes

Currently, the Check command expanded column contains data only for active checks. And when it does, it merely duplicates the Check command column, resulting in redundant information:

Ideally, the Check command column should include only the check name (e.g. check_mk_active-httpv2) without arguments (!…). This would make both columns more meaningful and clearly distinct.

Alternatively, introducing a dedicated Check name column could be even more effective. For instance, it could display mrpe-my_super_duper_test instead of the generic check_mk-mrpe currently shown in Check command , ensuring more precise and useful data for analysis and automation.

These changes would make the columns more practical across different use cases, eliminate unnecessary workarounds, and significantly improve long-term usability.

2 Likes

Hi Martin,

the cron causes OOM in our 2.5.0p2 Pro and Community editions and is automatically starting. Both options over WATO Do not collect product usage data as well as Disabled Reminder scheduled don’t have any effect on both versions, it still runs randomly on only 2 sites and causes OOM as mentioned. We have a distributed setup with both versions, separated of course, config is disabled on the satellites and is distributed only over the master. The weird thing is that the cron is triggered only on these 2 sites.
Do you have an advice how to disable it completely?

Best regards

Hello @3c2c2ff5 ,

thank you for flagging - just confirming that we have seen your message and will look into it.

Hi Annika,

thanks for the quick response. One more thing, when I kill the $PID, it remains off, only when when the site is restarted it is triggered and hangs, so I need to manually kill the $PID again. I tried to comment out the cron, but it is uncommented after a site restart, or a VM restart. If it is relevant to you, we have the same setup with the pro and community editions, the same sites, same config, same rules, running on different VMs and the same agents in our infrastructure. But as I mentioned, only on two sites the cron is triggered, $SITE1 pro and its counterpart $SITE1 community, all other sites are not affected.

EDIT
one more weird thing, when I restart the site on either of them, the cron is triggered on the other one as well. I don’t know how are they related, but they have different hostnames, different IPs and each is a satellite on a different setup. I double checked the Distributed monitoring.

Best regards

Hi Annika,

I think I fixed it. I had to logout of both sites in Distributed monitoring on both setups and login again. Probably this was a side effect of the downgrade to the community edition. It seems like simply changing the TCP address (FQDN), the URL prefix and the URL of the remote site is not sufficient, I needed to logout of the site and login again.
Now 10 minutes later it looks very good in comparison as the cron was immediately triggered on both sites. But I still wonder why it didn’t happen to the other sites! Nevertheless it is solved now and I’ll repeat the logout/login on all sites on both setups to avoid any future side effects.

EDIT:
cmk-product-usage --dry-run still hangs on both sides, even though the original problem with triggering the cron on the counterpart site is gone. It runs smoothly on all other sites and their counterparts

EDIT2:
an hour later the cron is triggered on both sites again and caused OOM.

Thank you very much

Hello @3c2c2ff5 ,

thanks for sharing what you tried so far - we’ll keep looking into this!

Hi Annika,

today the --dry-run worked for a brief moment on the RAW edition and minutes after it went to the same freezing behavior. Now I am pretty positive it is related to livestatus. This is from ~var/log/livestatus.log on the RAW site:

2026-05-22 07:07:48 [main] created core abstraction with 434 hosts, 5 host groups, 17554 services, 9 service groups, 2 contacts, 2 contact groups
2026-05-22 07:07:48 [main] log file = "/omd/sites/$SITE/var/nagios/livestatus.log"
2026-05-22 07:07:48 [main] crash reports directory = "/omd/sites/$SITE/var/check_mk/crashes"
2026-05-22 07:07:48 [main] license usage history file = "/omd/sites/$SITE/var/check_mk/licensing/history.json"
2026-05-22 07:07:48 [main] inventory directory = "/omd/sites/$SITE/var/check_mk/inventory"
2026-05-22 07:07:48 [main] structured status directory = ""
2026-05-22 07:07:48 [main] Robotmk HTML log directory = "/omd/sites/$SITE/var/robotmk/html_logs"
2026-05-22 07:07:48 [main] logwatch directory = "/omd/sites/$SITE/var/check_mk/logwatch"
2026-05-22 07:07:48 [main] prediction directory = ""
2026-05-22 07:07:48 [main] event console status socket = "/omd/sites/$SITE/tmp/run/mkeventd/status"
2026-05-22 07:07:48 [main] Livestatus socket = "/omd/sites/$SITE/tmp/run/live"
2026-05-22 07:07:48 [main] history file = "/omd/sites/$SITE/var/nagios/nagios.log"
2026-05-22 07:07:48 [main] history archive directory = "/omd/sites/$SITE/var/nagios/archive"
2026-05-22 07:07:48 [main] RRD multiple directory = "/opt/omd/sites/$SITE/var/pnp4nagios/perfdata"
2026-05-22 07:07:48 [main] rrdcached socket = "/omd/sites/$SITE/tmp/run/rrdcached.sock"
2026-05-22 07:09:20 [client 20] ignoring duplicate log file "/omd/sites/$SITE/var/nagios/archive/nagios-11-13-2020-00.log"
2026-05-22 07:10:40 [client 17] error: terminating client connection: unexpected EOF
2026-05-22 07:14:03 [client 13] error: terminating client connection: unexpected EOF

and this is from ~var/log/product_usage_analytics.log on the PRO site:

2026-05-22 06:23:03,432 [20] [cmk.product_usage 26183] Collection starts
2026-05-22 06:23:03,433 [40] [cmk.product_usage 26183] Unexpected error
Traceback (most recent call last):
  File "/omd/sites/$SITE/lib/python3.13/site-packages/cmk/livestatus_client/_connection.py", line 629, in _create_new_socket_connection
    site_socket.connect(address)
    ~~~~~~~~~~~~~~~~~~~^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/omd/sites/$SITE/lib/python3/cmk/product_usage_cli.py", line 92, in main
    data = collect_data(
        paths.var_dir,
    ...<2 lines>... 
        logger,
    )
  File "/omd/sites/$SITE/lib/python3/cmk/product_usage/collection.py", line 21, in collect_data
    site_info = site_info_collector.collect(cmk_config_dir, var_dir, omd_root)
  File "/omd/sites/$SITE/lib/python3/cmk/product_usage/collectors/site_info.py", line 28, in collect
    site_status = get_site_status()
  File "/omd/sites/$SITE/lib/python3/cmk/product_usage/collectors/site_info.py", line 88, in get_site_status
    response = connection.query(query)
  File "/omd/sites/$SITE/lib/python3.13/site-packages/cmk/livestatus_client/_connection.py", line 913, in query
    response = self.do_query(normalized_query, normalized_add_headers)
  File "/omd/sites/$SITE/lib/python3.13/site-packages/cmk/livestatus_client/_connection.py", line 734, in do_query
    self.send_query(str_query)
    ~~~~~~~~~~~~~~~^^^^^^^^^^^
  File "/omd/sites/$SITE/lib/python3.13/site-packages/cmk/livestatus_client/_connection.py", line 765, in send_query
    self.connect()
    ~~~~~~~~~~~~^^
  File "/omd/sites/$SITE/lib/python3.13/site-packages/cmk/livestatus_client/_connection.py", line 603, in connect
    site_socket = self._create_new_socket_connection()
  File "/omd/sites/$SITE/lib/python3.13/site-packages/cmk/livestatus_client/_connection.py", line 652, in _create_new_socket_connection
    raise MKLivestatusSocketError(f"Cannot connect to '{self.socketurl}': {e}")
cmk.livestatus_client._connection.MKLivestatusSocketError: Cannot connect to 'unix:/omd/sites/$SITE/tmp/run/live': [Errno 2] No such file or directory

as if they try to connect to each other through the local socket, distributed monitoring on the PRO setup is encrypted, while it is in plain text on the community setup.

~/livestatus.py just hangs while it tries to read from the socket

~$ cmk-product-usage --dry-run
^CTraceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/omd/sites/$SITE/lib/python3/cmk/product_usage_cli.py", line 170, in <module>
    sys.exit(main(sys.argv[1:]))
             ~~~~^^^^^^^^^^^^^^
  File "/omd/sites/$SITE/lib/python3/cmk/product_usage_cli.py", line 67, in main
    config = load_config(logger)
  File "/omd/sites/$SITE/lib/python3/cmk/product_usage_cli.py", line 46, in load_config
    get_builtin_host_labels=make_app(edition(paths.omd_root)).get_builtin_host_labels,
                            ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/omd/sites/$SITE/lib/python3/cmk/base/app.py", line 35, in make_app
    from cmk.base.community_app import make_app
  File "/omd/sites/$SITE/lib/python3/cmk/base/community_app.py", line 8, in <module>
    from cmk.base import notify
  File "/omd/sites/$SITE/lib/python3/cmk/base/notify.py", line 43, in <module>
    import livestatus
  File "/opt/omd/sites/$SITE/livestatus.py", line 25, in <module>
    chunks.append(sock.recv(4096))
                  ~~~~~~~~~^^^^^^
KeyboardInterrupt

Thanks a lot

I think the problem is ~/livestatus.py the file shouldn’t be there. I believe one of my colleges was testing/debugging things and created this file. So it was restored on the RAW/community. That explains why only these two sites have the issue. I just removed it and things seem to work again on both sites.

~$ locate "livestatus.py"
/opt/omd/sites/$SITE/livestatus.py
/opt/omd/versions/2.4.0p29.cre/lib/python3/cmk/gui/data_source/livestatus.py
/opt/omd/versions/2.4.0p29.cre/lib/python3/cmk/gui/mkeventd/livestatus.py
/opt/omd/versions/2.4.0p29.cre/lib/python3/cmk/gui/visuals/_livestatus.py
/opt/omd/versions/2.5.0p2.community/lib/python3/cmk/gui/data_source/livestatus.py
/opt/omd/versions/2.5.0p2.community/lib/python3/cmk/gui/visuals/_livestatus.py

IMHO maybe these tools shouldn’t take in consideration files outside the imported modules, I am aware the file existed in $OMD_ROOT, but it shouldn’t be relevant and should be ignored, as the needed files are imported with the modules.

Thanks for your time and sorry for the inconvenience

Hi @3c2c2ff5 ,

Thanks again for taking the time to report this and sharing your approach to fix it with us, this helped us tracking down the issue!

We’re releasing Werk 19607 to fix the root cause: unrelated files that happened to share a name were being picked up by the product analytics component, which caused tool failures and ultimately the OOM issue you experienced.

Full details here: Werk #19607: Product usage analytics: Stray files can no longer shadow the CLI tool

Thank you again and please let us know if something doesn’t work as expected,
Annika