Browse Source

feat(dev): Lighter devserver (#20062)

Markus Unterwaditzer 4 years ago
parent
commit
b97365ec64

+ 1 - 2
api-docs/generator.py

@@ -26,7 +26,7 @@ client = get_docker_client()
 namespace = "apidocs"
 
 # Define our set of containers we want to run
-APIDOC_CONTAINERS = ["postgres", "redis", "clickhouse", "snuba", "relay", "reverse_proxy"]
+APIDOC_CONTAINERS = ["postgres", "redis", "clickhouse", "snuba", "relay"]
 devservices_settings = {
     container_name: SENTRY_DEVSERVICES[container_name] for container_name in APIDOC_CONTAINERS
 }
@@ -47,7 +47,6 @@ apidoc_containers_overrides = {
         "only_if": None,
     },
     "relay": {"pull": None, "volumes": None, "only_if": None, "with_devserver": None},
-    "reverse_proxy": {"volumes": None, "only_if": None, "with_devserver": None},
 }
 
 

+ 1 - 1
config/relay/config.yml

@@ -1,6 +1,6 @@
 ---
 relay:
-  upstream: 'http://host.docker.internal:8888/'
+  upstream: 'http://host.docker.internal:8000/'
   host: 0.0.0.0
   port: 3000
 logging:

+ 0 - 51
config/reverse_proxy/nginx.conf

@@ -1,51 +0,0 @@
-user  nginx;
-worker_processes  1;
-
-error_log  /var/log/nginx/error.log warn;
-pid        /var/run/nginx.pid;
-
-
-events {
-    worker_connections  1024;
-}
-
-
-http {
-    include       /etc/nginx/mime.types;
-    default_type  application/octet-stream;
-
-    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
-                      '$status $body_bytes_sent "$http_referer" '
-                      '"$http_user_agent" "$http_x_forwarded_for"';
-
-    access_log  off;
-
-    sendfile              on;
-    keepalive_timeout     65;
-    client_max_body_size  100m;
-
-    # Do not use upstream directive to prevent nginx from resolving eagerly and
-    # crashing the devserver (if running the devservice using with_devserver
-    # option).
-
-    server {
-        listen 80;
-        resolver 127.0.0.11 ipv6=off;
-
-        set $upstream_relay sentry_relay.sentry:3000;
-        set $upstream_sentry host.docker.internal:8888;
-
-        location /api/store/ {
-            proxy_pass http://$upstream_relay;
-        }
-        # All supported ingest endpoints
-        location ~ ^/api/[1-9]\d*/ {
-            proxy_pass http://$upstream_relay;
-        }
-        location / {
-           proxy_pass http://$upstream_sentry;
-        }
-
-        proxy_set_header Host $host;
-    }
-}

+ 2 - 16
src/sentry/conf/server.py

@@ -117,10 +117,6 @@ RELAY_CONFIG_DIR = os.path.normpath(
     os.path.join(PROJECT_ROOT, os.pardir, os.pardir, "config", "relay")
 )
 
-REVERSE_PROXY_CONFIG = os.path.normpath(
-    os.path.join(PROJECT_ROOT, os.pardir, os.pardir, "config", "reverse_proxy", "nginx.conf")
-)
-
 sys.path.insert(0, os.path.normpath(os.path.join(PROJECT_ROOT, os.pardir)))
 
 DATABASES = {
@@ -1400,8 +1396,6 @@ SENTRY_WATCHERS = (
 # rest will be forwarded to Sentry)
 SENTRY_USE_RELAY = True
 SENTRY_RELAY_PORT = 3000
-SENTRY_REVERSE_PROXY_PORT = 8000
-
 
 # The chunk size for attachments in blob store. Should be a power of two.
 SENTRY_ATTACHMENT_BLOB_SIZE = 8 * 1024 * 1024  # 8MB
@@ -1528,16 +1522,6 @@ SENTRY_DEVSERVICES = {
         "command": ["run"],
         "only_if": lambda settings, options: options.get("symbolicator.enabled"),
     },
-    "proxy": {
-        "image": "nginx:1.16.1",
-        "ports": {"80/tcp": SENTRY_REVERSE_PROXY_PORT},
-        "volumes": {REVERSE_PROXY_CONFIG: {"bind": "/etc/nginx/nginx.conf"}},
-        "only_if": lambda settings, options: settings.SENTRY_USE_RELAY,
-        # This directive tells `devservices up` that the reverse_proxy is not to be
-        # started up, only pulled and made available for `devserver` which will start
-        # it with `devservices attach --is-devserver reverse_proxy`.
-        "with_devserver": True,
-    },
     "relay": {
         "image": "us.gcr.io/sentryio/relay:latest",
         "pull": True,
@@ -1934,3 +1918,5 @@ SENTRY_MAIL_ADAPTER_BACKEND = "sentry.mail.adapter.MailAdapter"
 # attributes, which can be identified through the whole processing pipeline and
 # observed mainly for producing stable metrics.
 SENTRY_SYNTHETIC_MONITORING_PROJECT_ID = None
+
+SENTRY_USE_UWSGI = True

+ 1 - 7
src/sentry/runner/commands/devserver.py

@@ -69,13 +69,7 @@ def devserver(
         raise click.ClickException("Not a daemon name: {}".format(", ".join(unrecognized_daemons)))
 
     if bind is None:
-        # default configuration, the dev server address depends on weather we have a reverse proxy
-        # in front that splits the requests between Relay and the dev server or we pass everything
-        # to the dev server
-        from django.conf import settings
-
-        port = 8888 if settings.SENTRY_USE_RELAY else 8000
-        bind = "127.0.0.1:{}".format(port)
+        bind = "127.0.0.1:8000"
 
     if ":" in bind:
         host, port = bind.split(":", 1)

+ 3 - 1
src/sentry/runner/commands/devservices.py

@@ -235,8 +235,10 @@ def _start_service(client, name, containers, project, fast=False, always_start=F
         listening = "(listening: %s)" % ", ".join(map(text_type, options["ports"].values()))
 
     # If a service is associated with the devserver, then do not run the created container.
-    # This was mainly added since it was not desirable for reverse_proxy to occupy port 8000 on the
+    # This was mainly added since it was not desirable for nginx to occupy port 8000 on the
     # first "devservices up".
+    # Nowadays that nginx is gone again, it's still nice to be able to shut
+    # down services within devserver.
     # See https://github.com/getsentry/sentry/pull/18362#issuecomment-616785458
     with_devserver = options.pop("with_devserver", False)
 

+ 3 - 28
src/sentry/runner/commands/run.py

@@ -85,15 +85,9 @@ def run():
 @click.option(
     "--noinput", default=False, is_flag=True, help="Do not prompt the user for input of any kind."
 )
-@click.option(
-    "--uwsgi/--no-uwsgi",
-    default=True,
-    is_flag=True,
-    help="Use uWSGI (default) or non-uWSGI (useful for debuggers such as PyCharm's)",
-)
 @log_options()
 @configuration
-def web(bind, workers, upgrade, with_lock, noinput, uwsgi):
+def web(bind, workers, upgrade, with_lock, noinput):
     "Run web service."
     if upgrade:
         click.echo("Performing upgrade before service startup...")
@@ -113,28 +107,9 @@ def web(bind, workers, upgrade, with_lock, noinput, uwsgi):
                 raise
 
     with managed_bgtasks(role="web"):
-        if not uwsgi:
-            click.echo(
-                "Running simple HTTP server. Note that chunked file "
-                "uploads will likely not work.",
-                err=True,
-            )
-
-            from django.conf import settings
-
-            host = bind[0] or settings.SENTRY_WEB_HOST
-            port = bind[1] or settings.SENTRY_WEB_PORT
-            click.echo("Address: http://%s:%s/" % (host, port))
-
-            from wsgiref.simple_server import make_server
-            from sentry.wsgi import application
-
-            httpd = make_server(host, port, application)
-            httpd.serve_forever()
-        else:
-            from sentry.services.http import SentryHTTPServer
+        from sentry.services.http import SentryHTTPServer
 
-            SentryHTTPServer(host=bind[0], port=bind[1], workers=workers).run()
+        SentryHTTPServer(host=bind[0], port=bind[1], workers=workers).run()
 
 
 @run.command()

+ 14 - 2
src/sentry/services/http.py

@@ -130,6 +130,8 @@ class SentryHTTPServer(Service):
         validate_settings(django_settings)
 
     def prepare_environment(self, env=None):
+        from django.conf import settings
+
         if env is None:
             env = os.environ
 
@@ -138,7 +140,7 @@ class SentryHTTPServer(Service):
             env.setdefault(k, v)
 
         # Signal that we're running within uwsgi
-        env["SENTRY_RUNNING_UWSGI"] = "1"
+        env["SENTRY_RUNNING_UWSGI"] = "1" if settings.SENTRY_USE_UWSGI else "0"
 
         # This has already been validated inside __init__
         env["SENTRY_SKIP_BACKEND_VALIDATION"] = "1"
@@ -155,4 +157,14 @@ class SentryHTTPServer(Service):
 
     def run(self):
         self.prepare_environment()
-        os.execvp("uwsgi", ("uwsgi",))
+        if os.environ.get("SENTRY_RUNNING_UWSGI") == "0":
+            from wsgiref.simple_server import make_server
+            from sentry.wsgi import application
+
+            assert os.environ.get("UWSGI_MODULE") == "sentry.wsgi:application"
+
+            host, port = os.environ["UWSGI_HTTP_SOCKET"].split(":")
+            httpd = make_server(host, int(port), application)
+            httpd.serve_forever()
+        else:
+            os.execvp("uwsgi", ("uwsgi",))

+ 8 - 1
webpack.config.js

@@ -430,11 +430,18 @@ if (
   if (!IS_UI_DEV_ONLY) {
     // This proxies to local backend server
     const backendAddress = `http://localhost:${SENTRY_BACKEND_PORT}/`;
+    const relayAddress = 'http://127.0.0.1:3000';
 
     appConfig.devServer = {
       ...appConfig.devServer,
       publicPath: '/_webpack',
-      proxy: {'!/_webpack': backendAddress},
+      // syntax for matching is using https://www.npmjs.com/package/micromatch
+      proxy: {
+        '/api/store/**': relayAddress,
+        '/api/{1..9}*({0..9})/**': relayAddress,
+        '/api/0/relays/outcomes/': relayAddress,
+        '!/_webpack': backendAddress,
+      },
       before: app =>
         app.use((req, _res, next) => {
           req.url = req.url.replace(/^\/_static\/[^\/]+\/sentry\/dist/, '/_webpack');