You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

131 lines
4.6 KiB

  1. # -*- coding: utf-8 -*-
  2. # Copyright 2020 The Matrix.org Foundation C.I.C.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. import typing
  16. from collections import Counter
  17. from twisted.internet import defer
  18. from synapse.metrics import BucketCollector
  19. from synapse.metrics.background_process_metrics import run_as_background_process
  20. from synapse.storage._base import SQLBaseStore
  21. from synapse.storage.database import DatabasePool
  22. from synapse.storage.databases.main.event_push_actions import (
  23. EventPushActionsWorkerStore,
  24. )
  25. class ServerMetricsStore(EventPushActionsWorkerStore, SQLBaseStore):
  26. """Functions to pull various metrics from the DB, for e.g. phone home
  27. stats and prometheus metrics.
  28. """
  29. def __init__(self, database: DatabasePool, db_conn, hs):
  30. super().__init__(database, db_conn, hs)
  31. # Collect metrics on the number of forward extremities that exist.
  32. # Counter of number of extremities to count
  33. self._current_forward_extremities_amount = (
  34. Counter()
  35. ) # type: typing.Counter[int]
  36. BucketCollector(
  37. "synapse_forward_extremities",
  38. lambda: self._current_forward_extremities_amount,
  39. buckets=[1, 2, 3, 5, 7, 10, 15, 20, 50, 100, 200, 500, "+Inf"],
  40. )
  41. # Read the extrems every 60 minutes
  42. def read_forward_extremities():
  43. # run as a background process to make sure that the database transactions
  44. # have a logcontext to report to
  45. return run_as_background_process(
  46. "read_forward_extremities", self._read_forward_extremities
  47. )
  48. hs.get_clock().looping_call(read_forward_extremities, 60 * 60 * 1000)
  49. async def _read_forward_extremities(self):
  50. def fetch(txn):
  51. txn.execute(
  52. """
  53. select count(*) c from event_forward_extremities
  54. group by room_id
  55. """
  56. )
  57. return txn.fetchall()
  58. res = await self.db_pool.runInteraction("read_forward_extremities", fetch)
  59. self._current_forward_extremities_amount = Counter([x[0] for x in res])
  60. @defer.inlineCallbacks
  61. def count_daily_messages(self):
  62. """
  63. Returns an estimate of the number of messages sent in the last day.
  64. If it has been significantly less or more than one day since the last
  65. call to this function, it will return None.
  66. """
  67. def _count_messages(txn):
  68. sql = """
  69. SELECT COALESCE(COUNT(*), 0) FROM events
  70. WHERE type = 'm.room.message'
  71. AND stream_ordering > ?
  72. """
  73. txn.execute(sql, (self.stream_ordering_day_ago,))
  74. (count,) = txn.fetchone()
  75. return count
  76. ret = yield self.db_pool.runInteraction("count_messages", _count_messages)
  77. return ret
  78. @defer.inlineCallbacks
  79. def count_daily_sent_messages(self):
  80. def _count_messages(txn):
  81. # This is good enough as if you have silly characters in your own
  82. # hostname then thats your own fault.
  83. like_clause = "%:" + self.hs.hostname
  84. sql = """
  85. SELECT COALESCE(COUNT(*), 0) FROM events
  86. WHERE type = 'm.room.message'
  87. AND sender LIKE ?
  88. AND stream_ordering > ?
  89. """
  90. txn.execute(sql, (like_clause, self.stream_ordering_day_ago))
  91. (count,) = txn.fetchone()
  92. return count
  93. ret = yield self.db_pool.runInteraction(
  94. "count_daily_sent_messages", _count_messages
  95. )
  96. return ret
  97. @defer.inlineCallbacks
  98. def count_daily_active_rooms(self):
  99. def _count(txn):
  100. sql = """
  101. SELECT COALESCE(COUNT(DISTINCT room_id), 0) FROM events
  102. WHERE type = 'm.room.message'
  103. AND stream_ordering > ?
  104. """
  105. txn.execute(sql, (self.stream_ordering_day_ago,))
  106. (count,) = txn.fetchone()
  107. return count
  108. ret = yield self.db_pool.runInteraction("count_daily_active_rooms", _count)
  109. return ret