mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-02-05 19:03:30 -05:00
Report data to newrelic
This commit is contained in:
3
.github/workflows/checks.yml
vendored
3
.github/workflows/checks.yml
vendored
@@ -7,8 +7,9 @@ permissions:
|
||||
|
||||
env:
|
||||
NOTIFY_ENVIRONMENT: test
|
||||
NEW_RELIC_CONFIG_FILE: newrelic.ini
|
||||
NEW_RELIC_ENVIRONMENT: test
|
||||
FLASK_APP: application.py
|
||||
FLASK_ENV: development
|
||||
WERKZEUG_DEBUG_PIN: off
|
||||
REDIS_ENABLED: 0
|
||||
NODE_VERSION: 16.15.1
|
||||
|
||||
3
.github/workflows/daily_checks.yml
vendored
3
.github/workflows/daily_checks.yml
vendored
@@ -11,8 +11,9 @@ permissions:
|
||||
|
||||
env:
|
||||
NOTIFY_ENVIRONMENT: test
|
||||
NEW_RELIC_CONFIG_FILE: newrelic.ini
|
||||
NEW_RELIC_ENVIRONMENT: test
|
||||
FLASK_APP: application.py
|
||||
FLASK_ENV: development
|
||||
WERKZEUG_DEBUG_PIN: off
|
||||
REDIS_ENABLED: 0
|
||||
NODE_VERSION: 16.15.1
|
||||
|
||||
3
Makefile
3
Makefile
@@ -25,7 +25,7 @@ watch-frontend: ## Build frontend and watch for changes
|
||||
|
||||
.PHONY: run-flask
|
||||
run-flask: ## Run flask
|
||||
pipenv run flask run -p 6012 --host=0.0.0.0
|
||||
pipenv run newrelic-admin run-program flask run -p 6012 --host=0.0.0.0
|
||||
|
||||
.PHONY: npm-audit
|
||||
npm-audit: ## Check for vulnerabilities in NPM packages
|
||||
@@ -48,6 +48,7 @@ py-lint: ## Run python linting scanners
|
||||
pipenv run isort --check-only ./app ./tests
|
||||
|
||||
.PHONY: py-test
|
||||
py-test: export NEW_RELIC_ENVIRONMENT=test
|
||||
py-test: ## Run python unit tests
|
||||
pipenv run py.test -n auto --maxfail=10 tests/
|
||||
|
||||
|
||||
2
Pipfile
2
Pipfile
@@ -31,8 +31,8 @@ pytz = "==2022.1"
|
||||
rtreelib = "==0.2.0"
|
||||
werkzeug = "~=2.2"
|
||||
wtforms = "==3.0.1"
|
||||
notifications-utils = {editable = true, ref = "main", git = "https://github.com/GSA/notifications-utils.git"}
|
||||
newrelic = "*"
|
||||
notifications-utils = {editable = true, ref = "request-unbound-error", git = "https://github.com/GSA/notifications-utils.git"}
|
||||
|
||||
[dev-packages]
|
||||
isort = "==5.10.1"
|
||||
|
||||
75
Pipfile.lock
generated
75
Pipfile.lock
generated
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "7dbbe21d77da5c1cfed8a33aeaf66af6d05f1ee36c1bdd60e5e87f7fababc3a4"
|
||||
"sha256": "04c7d4f97a5d60595b87980ef748d3ed77587067943f5e44a88ff3451a119f20"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
@@ -49,19 +49,19 @@
|
||||
},
|
||||
"boto3": {
|
||||
"hashes": [
|
||||
"sha256:0b1f82d4565ed875c7975ac0be5665e8d948613c01bcb0e49df6d4f5af670cc8",
|
||||
"sha256:319ddb274f8f83b035b88a3b127c465bf6fe3e3fc2d668869b489e992c47ca77"
|
||||
"sha256:4e876ba5d64928cde0c416dd844f04f22d6b73d14002bbc3ca55591f80f49927",
|
||||
"sha256:c729bb0af76e85a2776b6bd3da8d9fa0f4b91b425eab51612aa53956f644ee23"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==1.26.52"
|
||||
"version": "==1.26.54"
|
||||
},
|
||||
"botocore": {
|
||||
"hashes": [
|
||||
"sha256:a0b89a33305cfa6251c6e1142deb7567e216e37e25363159f45fb81dc5b474e5",
|
||||
"sha256:de55b6333fb13c66da9055972d7e4efff5dcc5a087478a2b70e99d888b29a24c"
|
||||
"sha256:ca3ef7588daa664fe196d3234718db5f6b5dab961507500b4bb921e31133eea1",
|
||||
"sha256:f2fe17ed6b8e163769a715f81cb6ce3d4628d172918de535256bdf34d29b704f"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==1.29.52"
|
||||
"version": "==1.29.54"
|
||||
},
|
||||
"cachetools": {
|
||||
"hashes": [
|
||||
@@ -693,7 +693,7 @@
|
||||
"notifications-utils": {
|
||||
"editable": true,
|
||||
"git": "https://github.com/GSA/notifications-utils.git",
|
||||
"ref": "d88d48026171991de4d8398e5f9f8c2063297885"
|
||||
"ref": "4e22e22524933bf81863f4ff105268c720ea40a1"
|
||||
},
|
||||
"numpy": {
|
||||
"hashes": [
|
||||
@@ -971,11 +971,11 @@
|
||||
},
|
||||
"setuptools": {
|
||||
"hashes": [
|
||||
"sha256:a78d01d1e2c175c474884671dde039962c9d74c7223db7369771fcf6e29ceeab",
|
||||
"sha256:bd6eb2d6722568de6d14b87c44a96fac54b2a45ff5e940e639979a3d1792adb6"
|
||||
"sha256:6f590d76b713d5de4e49fe4fbca24474469f53c83632d5d0fd056f7ff7e8112b",
|
||||
"sha256:ac4008d396bc9cd983ea483cb7139c0240a07bbc74ffb6232fceffedc6cf03a8"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==66.0.0"
|
||||
"version": "==66.1.1"
|
||||
},
|
||||
"shapely": {
|
||||
"hashes": [
|
||||
@@ -1139,19 +1139,19 @@
|
||||
},
|
||||
"boto3": {
|
||||
"hashes": [
|
||||
"sha256:0b1f82d4565ed875c7975ac0be5665e8d948613c01bcb0e49df6d4f5af670cc8",
|
||||
"sha256:319ddb274f8f83b035b88a3b127c465bf6fe3e3fc2d668869b489e992c47ca77"
|
||||
"sha256:4e876ba5d64928cde0c416dd844f04f22d6b73d14002bbc3ca55591f80f49927",
|
||||
"sha256:c729bb0af76e85a2776b6bd3da8d9fa0f4b91b425eab51612aa53956f644ee23"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==1.26.52"
|
||||
"version": "==1.26.54"
|
||||
},
|
||||
"botocore": {
|
||||
"hashes": [
|
||||
"sha256:a0b89a33305cfa6251c6e1142deb7567e216e37e25363159f45fb81dc5b474e5",
|
||||
"sha256:de55b6333fb13c66da9055972d7e4efff5dcc5a087478a2b70e99d888b29a24c"
|
||||
"sha256:ca3ef7588daa664fe196d3234718db5f6b5dab961507500b4bb921e31133eea1",
|
||||
"sha256:f2fe17ed6b8e163769a715f81cb6ce3d4628d172918de535256bdf34d29b704f"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==1.29.52"
|
||||
"version": "==1.29.54"
|
||||
},
|
||||
"cachecontrol": {
|
||||
"extras": [
|
||||
@@ -1335,13 +1335,6 @@
|
||||
"markers": "python_full_version >= '3.6.0'",
|
||||
"version": "==3.0.1"
|
||||
},
|
||||
"commonmark": {
|
||||
"hashes": [
|
||||
"sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60",
|
||||
"sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"
|
||||
],
|
||||
"version": "==0.9.1"
|
||||
},
|
||||
"cryptography": {
|
||||
"hashes": [
|
||||
"sha256:1a6915075c6d3a5e1215eab5d99bcec0da26036ff2102a1038401d6ef5bef25b",
|
||||
@@ -1501,6 +1494,14 @@
|
||||
],
|
||||
"version": "==0.12.2"
|
||||
},
|
||||
"markdown-it-py": {
|
||||
"hashes": [
|
||||
"sha256:93de681e5c021a432c63147656fe21790bc01231e0cd2da73626f1aa3ac0fe27",
|
||||
"sha256:cf7e59fed14b5ae17c0006eff14a2d9a00ed5f3a846148153899a0224e2c07da"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==2.1.0"
|
||||
},
|
||||
"markupsafe": {
|
||||
"hashes": [
|
||||
"sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed",
|
||||
@@ -1564,6 +1565,14 @@
|
||||
],
|
||||
"version": "==0.6.1"
|
||||
},
|
||||
"mdurl": {
|
||||
"hashes": [
|
||||
"sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8",
|
||||
"sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==0.1.2"
|
||||
},
|
||||
"moto": {
|
||||
"hashes": [
|
||||
"sha256:20607a0fd0cf6530e05ffb623ca84d3f45d50bddbcec2a33705a0cf471e71289",
|
||||
@@ -1671,11 +1680,11 @@
|
||||
},
|
||||
"pip-audit": {
|
||||
"hashes": [
|
||||
"sha256:3ea2fc5c70bf335362d4d81a7bd1084787efac34929e422f79bd8cf8804da2e2",
|
||||
"sha256:e0c9fe070a16aefdbb9c4d43df6a0183bc951375a293f58264c5e80b5edb57d7"
|
||||
"sha256:1259629fe24302e257052e977146f56bebf34927740d5efd184aaafa3b1b3b38",
|
||||
"sha256:f9632b9f67bcf3fda78ef7651a03c8ed926d1eaeda474dcbdcb26a5518dd6ffc"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.4.13"
|
||||
"version": "==2.4.14"
|
||||
},
|
||||
"pip-requirements-parser": {
|
||||
"hashes": [
|
||||
@@ -1874,11 +1883,11 @@
|
||||
},
|
||||
"rich": {
|
||||
"hashes": [
|
||||
"sha256:81c73a30b144bbcdedc13f4ea0b6ffd7fdc3b0d3cc259a9402309c8e4aee1964",
|
||||
"sha256:f846bff22a43e8508aebf3f0f2410ce1c6f4cde429098bd58d91fde038c57299"
|
||||
"sha256:7c963f0d03819221e9ac561e1bc866e3f95a02248c1234daa48954e6d381c003",
|
||||
"sha256:f1a00cdd3eebf999a15d85ec498bfe0b1a77efe9b34f645768a54132ef444ac5"
|
||||
],
|
||||
"markers": "python_full_version >= '3.7.0'",
|
||||
"version": "==13.1.0"
|
||||
"version": "==13.2.0"
|
||||
},
|
||||
"s3transfer": {
|
||||
"hashes": [
|
||||
@@ -1890,11 +1899,11 @@
|
||||
},
|
||||
"setuptools": {
|
||||
"hashes": [
|
||||
"sha256:a78d01d1e2c175c474884671dde039962c9d74c7223db7369771fcf6e29ceeab",
|
||||
"sha256:bd6eb2d6722568de6d14b87c44a96fac54b2a45ff5e940e639979a3d1792adb6"
|
||||
"sha256:6f590d76b713d5de4e49fe4fbca24474469f53c83632d5d0fd056f7ff7e8112b",
|
||||
"sha256:ac4008d396bc9cd983ea483cb7139c0240a07bbc74ffb6232fceffedc6cf03a8"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==66.0.0"
|
||||
"version": "==66.1.1"
|
||||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
|
||||
@@ -22,7 +22,7 @@ applications:
|
||||
NOTIFY_APP_NAME: admin
|
||||
NOTIFY_LOG_LEVEL: INFO
|
||||
FLASK_APP: application.py
|
||||
FLASK_ENV: production
|
||||
FLASK_DEBUG: "false"
|
||||
REDIS_ENABLED: ((REDIS_ENABLED))
|
||||
ADMIN_BASE_URL: https://((public_admin_route))
|
||||
API_HOST_NAME: https://notify-api-((env)).apps.internal:61443
|
||||
|
||||
222
newrelic.ini
Normal file
222
newrelic.ini
Normal file
@@ -0,0 +1,222 @@
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
#
|
||||
# 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:
|
||||
#
|
||||
# http://newrelic.com/docs/python/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 key binds the Python Agent's data to your
|
||||
# account in the New Relic service.
|
||||
# license_key is set via NEW_RELIC_LICENSE_KEY env var
|
||||
|
||||
host = gov-collector.newrelic.com
|
||||
|
||||
# The application name. Set this to be the name of your
|
||||
# application as you would like it to show up in New Relic UI.
|
||||
# The UI will then auto-map instances of your application into a
|
||||
# entry on your home dashboard page.
|
||||
app_name = us-notify-admin (Development)
|
||||
|
||||
# New Relic offers distributed tracing for monitoring and analyzing modern
|
||||
# distributed systems.Enable distributed tracing.
|
||||
distributed_tracing.enabled = true
|
||||
|
||||
# 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.
|
||||
monitor_mode = true
|
||||
|
||||
# Sets the name of a file to log agent messages to. Useful for
|
||||
# debugging any issues with the agent. This is not set by
|
||||
# default as it is not known in advance what user your web
|
||||
# application processes will run as and where they have
|
||||
# permission to write 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 to the file. If not able to
|
||||
# write 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.
|
||||
#log_file = /tmp/newrelic-python-agent.log
|
||||
|
||||
# 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.
|
||||
log_level = info
|
||||
|
||||
# The Python Agent communicates with the New Relic service using
|
||||
# SSL by default. Note that this does result in an increase in
|
||||
# CPU overhead, over and above what would occur for a non SSL
|
||||
# connection, to perform the encryption involved in the SSL
|
||||
# communication. This work is though done in a distinct thread
|
||||
# to those handling your web requests, so it should not impact
|
||||
# response times. You can if you wish revert to using a non SSL
|
||||
# connection, but this will result in information being sent
|
||||
# over a plain socket connection and will not be as secure.
|
||||
ssl = true
|
||||
|
||||
# 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
|
||||
# SSL is turned on, 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. 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.
|
||||
# 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.
|
||||
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_errors =
|
||||
|
||||
# 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.
|
||||
thread_profiler.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]
|
||||
app_name = us-notify-admin (Development)
|
||||
|
||||
[newrelic:test]
|
||||
app_name = us-notify-admin (Test)
|
||||
monitor_mode = false
|
||||
|
||||
[newrelic:sandbox]
|
||||
app_name = us-notify-admin (Sandbox)
|
||||
monitor_mode = false
|
||||
|
||||
[newrelic:staging]
|
||||
app_name = us-notify-admin (Staging)
|
||||
monitor_mode = true
|
||||
|
||||
[newrelic:demo]
|
||||
app_name = us-notify-admin (Demo)
|
||||
monitor_mode = true
|
||||
|
||||
[newrelic:production]
|
||||
app_name = us-notify-admin
|
||||
monitor_mode = true
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -21,7 +21,7 @@ AWS_SECRET_ACCESS_KEY="don't write secrets to the sample file"
|
||||
# Application
|
||||
NOTIFY_ENVIRONMENT=development
|
||||
FLASK_APP=application.py
|
||||
FLASK_ENV=development
|
||||
FLASK_DEBUG=true
|
||||
WERKZEUG_DEBUG_PIN=off
|
||||
|
||||
NODE_VERSION=16.15.1
|
||||
@@ -35,3 +35,9 @@ NODE_VERSION=16.15.1
|
||||
# Local direct setup
|
||||
API_HOST_NAME=http://localhost:6011
|
||||
REDIS_URL=redis://localhost:6379/0
|
||||
|
||||
#############################################################
|
||||
|
||||
# New Relic
|
||||
NEW_RELIC_CONFIG_FILE=newrelic.ini
|
||||
NEW_RELIC_LICENSE_KEY="don't write secrets to the sample file"
|
||||
|
||||
Reference in New Issue
Block a user