add NewRelic
This commit is contained in:
21
main.py
21
main.py
@@ -29,6 +29,27 @@ from app.service.init_geoip import init_geoip
|
|||||||
from app.service.osu_rx_statistics import create_rx_statistics
|
from app.service.osu_rx_statistics import create_rx_statistics
|
||||||
from app.service.recalculate import recalculate
|
from app.service.recalculate import recalculate
|
||||||
|
|
||||||
|
# 检查 New Relic 配置文件是否存在,如果存在则初始化 New Relic
|
||||||
|
newrelic_config_path = os.path.join(os.path.dirname(__file__), "newrelic.ini")
|
||||||
|
if os.path.exists(newrelic_config_path):
|
||||||
|
try:
|
||||||
|
import newrelic.agent
|
||||||
|
|
||||||
|
environment = os.environ.get(
|
||||||
|
"NEW_RELIC_ENVIRONMENT",
|
||||||
|
"production" if not settings.debug else "development"
|
||||||
|
)
|
||||||
|
|
||||||
|
newrelic.agent.initialize(newrelic_config_path, environment)
|
||||||
|
logger.info(f"[NewRelic] Enabled, environment: {environment}")
|
||||||
|
except ImportError:
|
||||||
|
logger.warning("[NewRelic] Config file found but 'newrelic' package is not installed")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"[NewRelic] Initialization failed: {e}")
|
||||||
|
else:
|
||||||
|
logger.info("[NewRelic] No newrelic.ini config file found, skipping initialization")
|
||||||
|
|
||||||
|
|
||||||
from fastapi import FastAPI, HTTPException, Request
|
from fastapi import FastAPI, HTTPException, Request
|
||||||
from fastapi.exceptions import RequestValidationError
|
from fastapi.exceptions import RequestValidationError
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
|
|||||||
255
newrelic.ini
Normal file
255
newrelic.ini
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#
|
||||||
|
# This file configures the New Relic Python Agent.
|
||||||
|
#
|
||||||
|
# The path to the configuration file should be supplied to the function
|
||||||
|
# newrelic.agent.initialize() when the agent is being initialized.
|
||||||
|
#
|
||||||
|
# The configuration file follows a structure similar to what you would
|
||||||
|
# find for Microsoft Windows INI files. For further information on the
|
||||||
|
# configuration file format see the Python ConfigParser documentation at:
|
||||||
|
#
|
||||||
|
# http://docs.python.org/library/configparser.html
|
||||||
|
#
|
||||||
|
# For further discussion on the behaviour of the Python agent that can
|
||||||
|
# be configured via this configuration file see:
|
||||||
|
#
|
||||||
|
# https://docs.newrelic.com/docs/apm/agents/python-agent/configuration/python-agent-configuration/
|
||||||
|
#
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Here are the settings that are common to all environments.
|
||||||
|
|
||||||
|
[newrelic]
|
||||||
|
|
||||||
|
# You must specify the license key associated with your New
|
||||||
|
# Relic account. This may also be set using the NEW_RELIC_LICENSE_KEY
|
||||||
|
# environment variable. This key binds the Python Agent's data to
|
||||||
|
# your account in the New Relic service. For more information on
|
||||||
|
# storing and generating license keys, see
|
||||||
|
# https://docs.newrelic.com/docs/apis/intro-apis/new-relic-api-keys/#ingest-license-key
|
||||||
|
license_key = 142680e050caa393c0aed741f717f1baFFFFNRAL
|
||||||
|
|
||||||
|
# The application name. Set this to be the name of your
|
||||||
|
# application as you would like it to show up in New Relic UI.
|
||||||
|
# You may also set this using the NEW_RELIC_APP_NAME environment variable.
|
||||||
|
# The UI will then auto-map instances of your application into a
|
||||||
|
# entry on your home dashboard page. You can also specify multiple
|
||||||
|
# app names to group your aggregated data. For further details,
|
||||||
|
# please see:
|
||||||
|
# https://docs.newrelic.com/docs/apm/agents/manage-apm-agents/app-naming/use-multiple-names-app/
|
||||||
|
app_name = g0v0-server
|
||||||
|
|
||||||
|
# When "true", the agent collects performance data about your
|
||||||
|
# application and reports this data to the New Relic UI at
|
||||||
|
# newrelic.com. This global switch is normally overridden for
|
||||||
|
# each environment below. It may also be set using the
|
||||||
|
# NEW_RELIC_MONITOR_MODE environment variable.
|
||||||
|
monitor_mode = true
|
||||||
|
|
||||||
|
# Sets the name of a file to log agent messages to. Whatever you
|
||||||
|
# set this to, you must ensure that the permissions for the
|
||||||
|
# containing directory and the file itself are correct, and
|
||||||
|
# that the user that your web application runs as can write out
|
||||||
|
# to the file. If not able to out a log file, it is also
|
||||||
|
# possible to say "stderr" and output to standard error output.
|
||||||
|
# This would normally result in output appearing in your web
|
||||||
|
# server log. It can also be set using the NEW_RELIC_LOG
|
||||||
|
# environment variable.
|
||||||
|
log_file = stdout
|
||||||
|
|
||||||
|
# Sets the level of detail of messages sent to the log file, if
|
||||||
|
# a log file location has been provided. Possible values, in
|
||||||
|
# increasing order of detail, are: "critical", "error", "warning",
|
||||||
|
# "info" and "debug". When reporting any agent issues to New
|
||||||
|
# Relic technical support, the most useful setting for the
|
||||||
|
# support engineers is "debug". However, this can generate a lot
|
||||||
|
# of information very quickly, so it is best not to keep the
|
||||||
|
# agent at this level for longer than it takes to reproduce the
|
||||||
|
# problem you are experiencing. This may also be set using the
|
||||||
|
# NEW_RELIC_LOG_LEVEL environment variable.
|
||||||
|
log_level = info
|
||||||
|
|
||||||
|
# High Security Mode enforces certain security settings, and prevents
|
||||||
|
# them from being overridden, so that no sensitive data is sent to New
|
||||||
|
# Relic. Enabling High Security Mode means that request parameters are
|
||||||
|
# not collected and SQL can not be sent to New Relic in its raw form.
|
||||||
|
# To activate High Security Mode, it must be set to 'true' in this
|
||||||
|
# local .ini configuration file AND be set to 'true' in the
|
||||||
|
# server-side configuration in the New Relic user interface. It can
|
||||||
|
# also be set using the NEW_RELIC_HIGH_SECURITY environment variable.
|
||||||
|
# For details, see
|
||||||
|
# https://docs.newrelic.com/docs/subscriptions/high-security
|
||||||
|
high_security = false
|
||||||
|
|
||||||
|
# The Python Agent will attempt to connect directly to the New
|
||||||
|
# Relic service. If there is an intermediate firewall between
|
||||||
|
# your host and the New Relic service that requires you to use a
|
||||||
|
# HTTP proxy, then you should set both the "proxy_host" and
|
||||||
|
# "proxy_port" settings to the required values for the HTTP
|
||||||
|
# proxy. The "proxy_user" and "proxy_pass" settings should
|
||||||
|
# additionally be set if proxy authentication is implemented by
|
||||||
|
# the HTTP proxy. The "proxy_scheme" setting dictates what
|
||||||
|
# protocol scheme is used in talking to the HTTP proxy. This
|
||||||
|
# would normally always be set as "http" which will result in the
|
||||||
|
# agent then using a SSL tunnel through the HTTP proxy for end to
|
||||||
|
# end encryption.
|
||||||
|
# See https://docs.newrelic.com/docs/apm/agents/python-agent/configuration/python-agent-configuration/#proxy
|
||||||
|
# for information on proxy configuration via environment variables.
|
||||||
|
# proxy_scheme = http
|
||||||
|
# proxy_host = hostname
|
||||||
|
# proxy_port = 8080
|
||||||
|
# proxy_user =
|
||||||
|
# proxy_pass =
|
||||||
|
|
||||||
|
# Capturing request parameters is off by default. To enable the
|
||||||
|
# capturing of request parameters, first ensure that the setting
|
||||||
|
# "attributes.enabled" is set to "true" (the default value), and
|
||||||
|
# then add "request.parameters.*" to the "attributes.include"
|
||||||
|
# setting. For details about attributes configuration, please
|
||||||
|
# consult the documentation.
|
||||||
|
# attributes.include = request.parameters.*
|
||||||
|
|
||||||
|
# The transaction tracer captures deep information about slow
|
||||||
|
# transactions and sends this to the UI on a periodic basis. The
|
||||||
|
# transaction tracer is enabled by default. Set this to "false"
|
||||||
|
# to turn it off.
|
||||||
|
transaction_tracer.enabled = true
|
||||||
|
|
||||||
|
# Threshold in seconds for when to collect a transaction trace.
|
||||||
|
# When the response time of a controller action exceeds this
|
||||||
|
# threshold, a transaction trace will be recorded and sent to
|
||||||
|
# the UI. Valid values are any positive float value, or (default)
|
||||||
|
# "apdex_f", which will use the threshold for a dissatisfying
|
||||||
|
# Apdex controller action - four times the Apdex T value.
|
||||||
|
transaction_tracer.transaction_threshold = apdex_f
|
||||||
|
|
||||||
|
# When the transaction tracer is on, SQL statements can
|
||||||
|
# optionally be recorded. The recorder has three modes, "off"
|
||||||
|
# which sends no SQL, "raw" which sends the SQL statement in its
|
||||||
|
# original form, and "obfuscated", which strips out numeric and
|
||||||
|
# string literals.
|
||||||
|
transaction_tracer.record_sql = obfuscated
|
||||||
|
|
||||||
|
# Threshold in seconds for when to collect stack trace for a SQL
|
||||||
|
# call. In other words, when SQL statements exceed this
|
||||||
|
# threshold, then capture and send to the UI the current stack
|
||||||
|
# trace. This is helpful for pinpointing where long SQL calls
|
||||||
|
# originate from in an application.
|
||||||
|
transaction_tracer.stack_trace_threshold = 0.5
|
||||||
|
|
||||||
|
# Determines whether the agent will capture query plans for slow
|
||||||
|
# SQL queries. Only supported in MySQL and PostgreSQL. Set this
|
||||||
|
# to "false" to turn it off.
|
||||||
|
transaction_tracer.explain_enabled = true
|
||||||
|
|
||||||
|
# Threshold for query execution time below which query plans
|
||||||
|
# will not not be captured. Relevant only when "explain_enabled"
|
||||||
|
# is true.
|
||||||
|
transaction_tracer.explain_threshold = 0.5
|
||||||
|
|
||||||
|
# Space separated list of function or method names in form
|
||||||
|
# 'module:function' or 'module:class.function' for which
|
||||||
|
# additional function timing instrumentation will be added.
|
||||||
|
transaction_tracer.function_trace =
|
||||||
|
|
||||||
|
# The error collector captures information about uncaught
|
||||||
|
# exceptions or logged exceptions and sends them to UI for
|
||||||
|
# viewing. The error collector is enabled by default. Set this
|
||||||
|
# to "false" to turn it off. For more details on errors, see
|
||||||
|
# https://docs.newrelic.com/docs/apm/agents/manage-apm-agents/agent-data/manage-errors-apm-collect-ignore-or-mark-expected/
|
||||||
|
error_collector.enabled = true
|
||||||
|
|
||||||
|
# To stop specific errors from reporting to the UI, set this to
|
||||||
|
# a space separated list of the Python exception type names to
|
||||||
|
# ignore. The exception name should be of the form 'module:class'.
|
||||||
|
error_collector.ignore_classes =
|
||||||
|
|
||||||
|
# Expected errors are reported to the UI but will not affect the
|
||||||
|
# Apdex or error rate. To mark specific errors as expected, set this
|
||||||
|
# to a space separated list of the Python exception type names to
|
||||||
|
# expected. The exception name should be of the form 'module:class'.
|
||||||
|
error_collector.expected_classes =
|
||||||
|
|
||||||
|
# Browser monitoring is the Real User Monitoring feature of the UI.
|
||||||
|
# For those Python web frameworks that are supported, this
|
||||||
|
# setting enables the auto-insertion of the browser monitoring
|
||||||
|
# JavaScript fragments.
|
||||||
|
browser_monitoring.auto_instrument = true
|
||||||
|
|
||||||
|
# A thread profiling session can be scheduled via the UI when
|
||||||
|
# this option is enabled. The thread profiler will periodically
|
||||||
|
# capture a snapshot of the call stack for each active thread in
|
||||||
|
# the application to construct a statistically representative
|
||||||
|
# call tree. For more details on the thread profiler tool, see
|
||||||
|
# https://docs.newrelic.com/docs/apm/apm-ui-pages/events/thread-profiler-tool/
|
||||||
|
thread_profiler.enabled = true
|
||||||
|
|
||||||
|
# Your application deployments can be recorded through the
|
||||||
|
# New Relic REST API. To use this feature provide your API key
|
||||||
|
# below then use the `newrelic-admin record-deploy` command.
|
||||||
|
# This can also be set using the NEW_RELIC_API_KEY
|
||||||
|
# environment variable.
|
||||||
|
# api_key =
|
||||||
|
|
||||||
|
# Distributed tracing lets you see the path that a request takes
|
||||||
|
# through your distributed system. For more information, please
|
||||||
|
# consult our distributed tracing planning guide.
|
||||||
|
# https://docs.newrelic.com/docs/transition-guide-distributed-tracing
|
||||||
|
distributed_tracing.enabled = true
|
||||||
|
|
||||||
|
# This setting enables log decoration, the forwarding of log events,
|
||||||
|
# and the collection of logging metrics if these sub-feature
|
||||||
|
# configurations are also enabled. If this setting is false, no
|
||||||
|
# logging instrumentation features are enabled. This can also be
|
||||||
|
# set using the NEW_RELIC_APPLICATION_LOGGING_ENABLED environment
|
||||||
|
# variable.
|
||||||
|
# application_logging.enabled = true
|
||||||
|
|
||||||
|
# If true, the agent captures log records emitted by your application
|
||||||
|
# and forwards them to New Relic. `application_logging.enabled` must
|
||||||
|
# also be true for this setting to take effect. You can also set
|
||||||
|
# this using the NEW_RELIC_APPLICATION_LOGGING_FORWARDING_ENABLED
|
||||||
|
# environment variable.
|
||||||
|
# application_logging.forwarding.enabled = true
|
||||||
|
|
||||||
|
# If true, the agent decorates logs with metadata to link to entities,
|
||||||
|
# hosts, traces, and spans. `application_logging.enabled` must also
|
||||||
|
# be true for this setting to take effect. This can also be set
|
||||||
|
# using the NEW_RELIC_APPLICATION_LOGGING_LOCAL_DECORATING_ENABLED
|
||||||
|
# environment variable.
|
||||||
|
# application_logging.local_decorating.enabled = true
|
||||||
|
|
||||||
|
# If true, the agent captures metrics related to the log lines
|
||||||
|
# being sent up by your application. This can also be set
|
||||||
|
# using the NEW_RELIC_APPLICATION_LOGGING_METRICS_ENABLED
|
||||||
|
# environment variable.
|
||||||
|
# application_logging.metrics.enabled = true
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#
|
||||||
|
# The application environments. These are specific settings which
|
||||||
|
# override the common environment settings. The settings related to a
|
||||||
|
# specific environment will be used when the environment argument to the
|
||||||
|
# newrelic.agent.initialize() function has been defined to be either
|
||||||
|
# "development", "test", "staging" or "production".
|
||||||
|
#
|
||||||
|
|
||||||
|
[newrelic:development]
|
||||||
|
monitor_mode = false
|
||||||
|
|
||||||
|
[newrelic:test]
|
||||||
|
monitor_mode = false
|
||||||
|
|
||||||
|
[newrelic:staging]
|
||||||
|
app_name = g0v0-server (Staging)
|
||||||
|
monitor_mode = true
|
||||||
|
|
||||||
|
[newrelic:production]
|
||||||
|
monitor_mode = true
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
@@ -17,6 +17,7 @@ dependencies = [
|
|||||||
"loguru>=0.7.3",
|
"loguru>=0.7.3",
|
||||||
"maxminddb>=2.8.2",
|
"maxminddb>=2.8.2",
|
||||||
"msgpack-lazer-api",
|
"msgpack-lazer-api",
|
||||||
|
"newrelic>=10.1.0",
|
||||||
"osupyparser>=1.0.7",
|
"osupyparser>=1.0.7",
|
||||||
"passlib[bcrypt]>=1.7.4",
|
"passlib[bcrypt]>=1.7.4",
|
||||||
"pillow>=11.3.0",
|
"pillow>=11.3.0",
|
||||||
|
|||||||
18
uv.lock
generated
18
uv.lock
generated
@@ -545,6 +545,7 @@ dependencies = [
|
|||||||
{ name = "loguru" },
|
{ name = "loguru" },
|
||||||
{ name = "maxminddb" },
|
{ name = "maxminddb" },
|
||||||
{ name = "msgpack-lazer-api" },
|
{ name = "msgpack-lazer-api" },
|
||||||
|
{ name = "newrelic" },
|
||||||
{ name = "osupyparser" },
|
{ name = "osupyparser" },
|
||||||
{ name = "passlib", extra = ["bcrypt"] },
|
{ name = "passlib", extra = ["bcrypt"] },
|
||||||
{ name = "pillow" },
|
{ name = "pillow" },
|
||||||
@@ -583,6 +584,7 @@ requires-dist = [
|
|||||||
{ name = "loguru", specifier = ">=0.7.3" },
|
{ name = "loguru", specifier = ">=0.7.3" },
|
||||||
{ name = "maxminddb", specifier = ">=2.8.2" },
|
{ name = "maxminddb", specifier = ">=2.8.2" },
|
||||||
{ name = "msgpack-lazer-api", editable = "packages/msgpack_lazer_api" },
|
{ name = "msgpack-lazer-api", editable = "packages/msgpack_lazer_api" },
|
||||||
|
{ name = "newrelic", specifier = ">=10.1.0" },
|
||||||
{ name = "osupyparser", git = "https://github.com/MingxuanGame/osupyparser.git" },
|
{ name = "osupyparser", git = "https://github.com/MingxuanGame/osupyparser.git" },
|
||||||
{ name = "passlib", extras = ["bcrypt"], specifier = ">=1.7.4" },
|
{ name = "passlib", extras = ["bcrypt"], specifier = ">=1.7.4" },
|
||||||
{ name = "pillow", specifier = ">=11.3.0" },
|
{ name = "pillow", specifier = ">=11.3.0" },
|
||||||
@@ -931,6 +933,22 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/fd/69/b547032297c7e63ba2af494edba695d781af8a0c6e89e4d06cf848b21d80/multidict-6.6.4-py3-none-any.whl", hash = "sha256:27d8f8e125c07cb954e54d75d04905a9bba8a439c1d84aca94949d4d03d8601c", size = 12313, upload-time = "2025-08-11T12:08:46.891Z" },
|
{ url = "https://files.pythonhosted.org/packages/fd/69/b547032297c7e63ba2af494edba695d781af8a0c6e89e4d06cf848b21d80/multidict-6.6.4-py3-none-any.whl", hash = "sha256:27d8f8e125c07cb954e54d75d04905a9bba8a439c1d84aca94949d4d03d8601c", size = 12313, upload-time = "2025-08-11T12:08:46.891Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "newrelic"
|
||||||
|
version = "10.16.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/d4/71/07c41fd5e8c94e95216b000d00c3cf735f769cb406c0f33c6ff83b7b7418/newrelic-10.16.0.tar.gz", hash = "sha256:d20eb934380a88d787f93e037d2ccfd5a7c80e657db5bb2e645216eaafe32e26", size = 1267210, upload-time = "2025-08-14T22:23:47.619Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/be/4b/ba14854270412686fdc331b1503b90554968e58d504297572bfc9cdaf3ad/newrelic-10.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f74301ed32ce625fb84c8bd0c079498dca603ff111d5baa2f59b6480ef7355b", size = 858772, upload-time = "2025-08-14T22:23:19.058Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/97/41/de8f0be9e285371cee22a8399840141ffb34ffa5462d31c80c5d7a951ed5/newrelic-10.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3efef3b10f02a086d9009a80b020db8f0b1db5072075779c9facd5d2fe3bb916", size = 858430, upload-time = "2025-08-14T22:23:20.658Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/52/74/2fc1e2d96029b57397eb3e2fae9f5e5840af3b98e896834b7a584f614b98/newrelic-10.16.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8328f621f3683b28156cfa8e1648a56b894480bf4c4953cde7e659b1480ae1e9", size = 856401, upload-time = "2025-08-14T22:23:21.981Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2a/42/fb73714fbf105b0c96faea68d17149dfecaa0209a6354b6a6d67c77ef65f/newrelic-10.16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:07f65faed0a9aa40695e6e6ce4c943ca9c9643fc848c2344bb26665a65893a80", size = 856270, upload-time = "2025-08-14T22:23:23.407Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/76/6d/47389d4a9390af2834f552d3bb7ed9b7c9ded30054409621e941ddbe1083/newrelic-10.16.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:053e73518cf0b2af412490723d3fa8338dab6ed48b748c0b7a0288160d1c33e2", size = 858759, upload-time = "2025-08-14T22:23:24.957Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b4/3e/9e44b713450c89d9d9b0a2626059014ad6e6699992fd687aec4cacb54b35/newrelic-10.16.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8263ae16eb4745def12bace2e3e38e013e76d4e765333a77342b270702e3eaa9", size = 858435, upload-time = "2025-08-14T22:23:26.536Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/61/a6/660dfd715011e2fef4d8e5f91c8c040f4ac125bc3bdc644ae0e514cbe87c/newrelic-10.16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e83e1341a72ac92118d1af40c2c3ba56069c589acceb1e89d236beab8d7891a", size = 856574, upload-time = "2025-08-14T22:23:28.041Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/59/9a/25935a1b999cef132a1597ca3686c028f5472e58d26bfe33876e8af38f4f/newrelic-10.16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:71950c5e1f26bf1ed563d3641da97f6bb209f80697675888ee12808d8ac69452", size = 856448, upload-time = "2025-08-14T22:23:29.483Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nodeenv"
|
name = "nodeenv"
|
||||||
version = "1.9.1"
|
version = "1.9.1"
|
||||||
|
|||||||
Reference in New Issue
Block a user