def convert(self, value, param, ctx): if value is None: return None # Providing a compatibility with splitting # the `events` queue until multiple queues # without the need to explicitly add them. queues = set() for queue in value.split(','): if queue == 'events': queues.add('events.preprocess_event') queues.add('events.process_event') queues.add('events.save_event') from sentry.runner.initializer import show_big_error show_big_error( [ 'DEPRECATED', '`events` queue no longer exists.', 'Switch to using:', '- events.preprocess_event', '- events.process_event', '- events.save_event', ] ) else: queues.add(queue) return frozenset(queues)
def start(ctx, service, bind, workers, upgrade, noinput): "DEPRECATED see `sentry run` instead." from sentry.runner.initializer import show_big_error show_big_error( [ '`sentry start%s` is deprecated.' % (' ' + service if 'http' in sys.argv else ''), 'Use `sentry run %s` instead.' % { 'http': 'web' }.get(service, service), ] ) if bind: if ':' in bind: host, port = bind.split(':', 1) port = int(port) else: host = bind port = None else: host, port = None, None if upgrade: click.echo('Performing upgrade before service startup...') from sentry.runner import call_command call_command( 'sentry.runner.commands.upgrade.upgrade', verbosity=0, noinput=noinput, ) click.echo('Running service: %r' % service) # remove command line arguments to avoid optparse failures with service code # that calls call_command which reparses the command line, and if --noupgrade is supplied # a parse error is thrown sys.argv = sys.argv[:1] from sentry.utils.imports import import_string import_string(SERVICES[service])( host=host, port=port, workers=workers, ).run()
def run_from_argv(self, argv): from sentry.runner.initializer import show_big_error if 'worker' in argv: show_big_error([ '`sentry celery worker` is deprecated.', 'Use `sentry run worker` instead.', ]) elif 'beat' in argv: show_big_error([ '`sentry celery beat` is deprecated.', 'Use `sentry run cron` instead.', ]) argv = self.handle_default_options(argv) if self.requires_model_validation: self.validate() base.execute_from_commandline( ['{0[0]} {0[1]}'.format(argv)] + argv[2:], )
def devserver(reload, watchers, workers, browser_reload, environment, bind): "Starts a lightweight web server for development." if ':' in bind: host, port = bind.split(':', 1) port = int(port) else: host = bind port = None import os os.environ['SENTRY_ENVIRONMENT'] = environment from django.conf import settings from sentry import options from sentry.services.http import SentryHTTPServer url_prefix = options.get('system.url-prefix', '') needs_https = url_prefix.startswith('https://') has_https = False if needs_https: from subprocess import check_output try: check_output(['which', 'https']) has_https = True except Exception: has_https = False from sentry.runner.initializer import show_big_error show_big_error([ 'missing `https` on your `$PATH`, but https is needed', '`$ brew install mattrobenolt/stuff/https`', ]) uwsgi_overrides = { # Make sure we don't try and use uwsgi protocol 'protocol': 'http', # Make sure we reload really quickly for local dev in case it # doesn't want to shut down nicely on it's own, NO MERCY 'worker-reload-mercy': 2, # We need stdin to support pdb in devserver 'honour-stdin': True, } if reload: uwsgi_overrides['py-autoreload'] = 1 daemons = [] if watchers: daemons += settings.SENTRY_WATCHERS if workers: if settings.CELERY_ALWAYS_EAGER: raise click.ClickException('Disable CELERY_ALWAYS_EAGER in your settings file to spawn workers.') daemons += [ ('worker', ['sentry', 'run', 'worker', '-c', '1', '--autoreload']), ('cron', ['sentry', 'run', 'cron', '--autoreload']), ] if needs_https and has_https: from six.moves.urllib.parse import urlparse parsed_url = urlparse(url_prefix) https_port = six.text_type(parsed_url.port or 443) https_host = parsed_url.hostname # Determine a random port for the backend http server import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((host, 0)) port = s.getsockname()[1] s.close() bind = '%s:%d' % (host, port) daemons += [ ('https', ['https', '-host', https_host, '-listen', host + ':' + https_port, bind]), ] # A better log-format for local dev when running through honcho, # but if there aren't any other daemons, we don't want to override. if daemons: uwsgi_overrides['log-format'] = '"%(method) %(uri) %(proto)" %(status) %(size)' else: uwsgi_overrides['log-format'] = '[%(ltime)] "%(method) %(uri) %(proto)" %(status) %(size)' server = SentryHTTPServer(host=host, port=port, workers=1, extra_options=uwsgi_overrides) # If we don't need any other daemons, just launch a normal uwsgi webserver # and avoid dealing with subprocesses if not daemons: return server.run() import sys from subprocess import list2cmdline from honcho.manager import Manager os.environ['PYTHONUNBUFFERED'] = 'true' if browser_reload: os.environ['WEBPACK_LIVERELOAD'] = '1' # Make sure that the environment is prepared before honcho takes over # This sets all the appropriate uwsgi env vars, etc server.prepare_environment() daemons += [ ('server', ['sentry', 'run', 'web']), ] cwd = os.path.realpath(os.path.join(settings.PROJECT_ROOT, os.pardir, os.pardir)) manager = Manager() for name, cmd in daemons: manager.add_process( name, list2cmdline(cmd), quiet=False, cwd=cwd, ) manager.loop() sys.exit(manager.returncode)
def devserver(reload, watchers, workers, browser_reload, bind): "Starts a lightweight web server for development." if ':' in bind: host, port = bind.split(':', 1) port = int(port) else: host = bind port = None import os from django.conf import settings from sentry import options from sentry.services.http import SentryHTTPServer url_prefix = options.get('system.url-prefix', '') needs_https = url_prefix.startswith('https://') has_https = False if needs_https: from subprocess import check_output try: check_output(['which', 'https']) has_https = True except Exception: has_https = False from sentry.runner.initializer import show_big_error show_big_error([ 'missing `https` on your `$PATH`, but https is needed', '`$ brew install mattrobenolt/stuff/https`', ]) uwsgi_overrides = { # Make sure we don't try and use uwsgi protocol 'protocol': 'http', # Make sure we reload really quickly for local dev in case it # doesn't want to shut down nicely on it's own, NO MERCY 'worker-reload-mercy': 2, # We need stdin to support pdb in devserver 'honour-stdin': True, } if reload: uwsgi_overrides['py-autoreload'] = 1 daemons = [] if watchers: daemons += settings.SENTRY_WATCHERS if workers: if settings.CELERY_ALWAYS_EAGER: raise click.ClickException( 'Disable CELERY_ALWAYS_EAGER in your settings file to spawn workers.' ) daemons += [ ('worker', ['sentry', 'run', 'worker', '-c', '1', '--autoreload']), ('cron', ['sentry', 'run', 'cron', '--autoreload']), ] if needs_https and has_https: from six.moves.urllib.parse import urlparse parsed_url = urlparse(url_prefix) https_port = six.text_type(parsed_url.port or 443) https_host = parsed_url.hostname # Determine a random port for the backend http server import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((host, 0)) port = s.getsockname()[1] s.close() bind = '%s:%d' % (host, port) daemons += [ ('https', [ 'https', '-host', https_host, '-listen', host + ':' + https_port, bind ]), ] # A better log-format for local dev when running through honcho, # but if there aren't any other daemons, we don't want to override. if daemons: uwsgi_overrides[ 'log-format'] = '"%(method) %(uri) %(proto)" %(status) %(size)' else: uwsgi_overrides[ 'log-format'] = '[%(ltime)] "%(method) %(uri) %(proto)" %(status) %(size)' server = SentryHTTPServer(host=host, port=port, workers=1, extra_options=uwsgi_overrides) # If we don't need any other daemons, just launch a normal uwsgi webserver # and avoid dealing with subprocesses if not daemons: return server.run() import sys from subprocess import list2cmdline from honcho.manager import Manager os.environ['PYTHONUNBUFFERED'] = 'true' if browser_reload: os.environ['WEBPACK_LIVERELOAD'] = '1' # Make sure that the environment is prepared before honcho takes over # This sets all the appropriate uwsgi env vars, etc server.prepare_environment() daemons += [ ('server', ['sentry', 'run', 'web']), ] cwd = os.path.realpath( os.path.join(settings.PROJECT_ROOT, os.pardir, os.pardir)) manager = Manager() for name, cmd in daemons: manager.add_process( name, list2cmdline(cmd), quiet=False, cwd=cwd, ) manager.loop() sys.exit(manager.returncode)
def devserver( reload, watchers, workers, experimental_spa, styleguide, prefix, environment, skip_daemons, bind ): "Starts a lightweight web server for development." skip_daemons = set(skip_daemons.split(",")) if skip_daemons else set() if skip_daemons.difference(_DEFAULT_DAEMONS.keys()): unrecognized_daemons = skip_daemons.difference(_DEFAULT_DAEMONS.keys()) 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) if ":" in bind: host, port = bind.split(":", 1) port = int(port) else: host = bind port = None import os os.environ["SENTRY_ENVIRONMENT"] = environment # NODE_ENV *must* use production for any prod-like environment as third party libraries look # for this magic constant os.environ["NODE_ENV"] = "production" if environment.startswith("prod") else environment from django.conf import settings from sentry import options from sentry.services.http import SentryHTTPServer url_prefix = options.get("system.url-prefix", "") parsed_url = urlparse(url_prefix) # Make sure we're trying to use a port that we can actually bind to needs_https = parsed_url.scheme == "https" and (parsed_url.port or 443) > 1024 has_https = False if needs_https: from subprocess import check_output try: check_output(["which", "https"]) has_https = True except Exception: has_https = False from sentry.runner.initializer import show_big_error show_big_error( [ "missing `https` on your `$PATH`, but https is needed", "`$ brew install mattrobenolt/stuff/https`", ] ) uwsgi_overrides = { "http-keepalive": True, # Make sure we reload really quickly for local dev in case it # doesn't want to shut down nicely on it's own, NO MERCY "worker-reload-mercy": 2, # We need stdin to support pdb in devserver "honour-stdin": True, # accept ridiculously large files "limit-post": 1 << 30, # do something with chunked "http-chunked-input": True, "thunder-lock": False, "timeout": 600, "harakiri": 600, } if reload: uwsgi_overrides["py-autoreload"] = 1 daemons = [] if experimental_spa: os.environ["SENTRY_UI_DEV_ONLY"] = "1" if not watchers: click.secho( "Using experimental SPA mode without watchers enabled has no effect", err=True, fg="yellow", ) # We proxy all requests through webpacks devserver on the configured port. # The backend is served on port+1 and is proxied via the webpack # configuration. if watchers: daemons += settings.SENTRY_WATCHERS proxy_port = port port = port + 1 uwsgi_overrides["protocol"] = "http" os.environ["FORCE_WEBPACK_DEV_SERVER"] = "1" os.environ["SENTRY_WEBPACK_PROXY_PORT"] = "%s" % proxy_port os.environ["SENTRY_BACKEND_PORT"] = "%s" % port # webpack and/or typescript is causing memory issues os.environ["NODE_OPTIONS"] = ( (os.environ.get("NODE_OPTIONS", "") + " --max-old-space-size=4096") ).lstrip() # Replace the webpack watcher with the drop-in webpack-dev-server webpack_config = next(w for w in daemons if w[0] == "webpack")[1] webpack_config[0] = os.path.join( *os.path.split(webpack_config[0])[0:-1] + ("webpack-dev-server",) ) daemons = [w for w in daemons if w[0] != "webpack"] + [("webpack", webpack_config)] else: # If we are the bare http server, use the http option with uwsgi protocol # See https://uwsgi-docs.readthedocs.io/en/latest/HTTP.html uwsgi_overrides.update( { # Make sure uWSGI spawns an HTTP server for us as we don't # have a proxy/load-balancer in front in dev mode. "http": "%s:%s" % (host, port), "protocol": "uwsgi", # This is needed to prevent https://git.io/fj7Lw "uwsgi-socket": None, } ) if workers: if settings.CELERY_ALWAYS_EAGER: raise click.ClickException( "Disable CELERY_ALWAYS_EAGER in your settings file to spawn workers." ) daemons += [_get_daemon("worker"), _get_daemon("cron")] from sentry import eventstream if eventstream.requires_post_process_forwarder(): daemons += [_get_daemon("post-process-forwarder")] if settings.SENTRY_USE_RELAY: daemons += [_get_daemon("ingest")] if needs_https and has_https: https_port = six.text_type(parsed_url.port) https_host = parsed_url.hostname # Determine a random port for the backend http server import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((host, 0)) port = s.getsockname()[1] s.close() bind = "%s:%d" % (host, port) daemons += [ ("https", ["https", "-host", https_host, "-listen", host + ":" + https_port, bind]) ] from sentry.runner.commands.devservices import _prepare_containers for name, container_options in _prepare_containers("sentry", silent=True).items(): if container_options.get("with_devserver", False): daemons += [(name, ["sentry", "devservices", "attach", "--fast", name])] # A better log-format for local dev when running through honcho, # but if there aren't any other daemons, we don't want to override. if daemons: uwsgi_overrides["log-format"] = '"%(method) %(status) %(uri) %(proto)" %(size)' else: uwsgi_overrides["log-format"] = '[%(ltime)] "%(method) %(status) %(uri) %(proto)" %(size)' server = SentryHTTPServer(host=host, port=port, workers=1, extra_options=uwsgi_overrides) # If we don't need any other daemons, just launch a normal uwsgi webserver # and avoid dealing with subprocesses if not daemons: return server.run() import sys from subprocess import list2cmdline from honcho.manager import Manager from honcho.printer import Printer os.environ["PYTHONUNBUFFERED"] = "true" # Make sure that the environment is prepared before honcho takes over # This sets all the appropriate uwsgi env vars, etc server.prepare_environment() daemons += [_get_daemon("server")] if styleguide: daemons += [_get_daemon("storybook")] cwd = os.path.realpath(os.path.join(settings.PROJECT_ROOT, os.pardir, os.pardir)) manager = Manager(Printer(prefix=prefix)) for name, cmd in daemons: if name not in skip_daemons: manager.add_process(name, list2cmdline(cmd), quiet=False, cwd=cwd) manager.loop() sys.exit(manager.returncode)
def devserver(reload, watchers, workers, browser_reload, styleguide, prefix, environment, bind): "Starts a lightweight web server for development." if ':' in bind: host, port = bind.split(':', 1) port = int(port) else: host = bind port = None import os os.environ['SENTRY_ENVIRONMENT'] = environment from django.conf import settings from sentry import options from sentry.services.http import SentryHTTPServer url_prefix = options.get('system.url-prefix', '') parsed_url = urlparse(url_prefix) # Make sure we're trying to use a port that we can actually bind to needs_https = (parsed_url.scheme == 'https' and (parsed_url.port or 443) > 1024) has_https = False if needs_https: from subprocess import check_output try: check_output(['which', 'https']) has_https = True except Exception: has_https = False from sentry.runner.initializer import show_big_error show_big_error([ 'missing `https` on your `$PATH`, but https is needed', '`$ brew install mattrobenolt/stuff/https`', ]) uwsgi_overrides = { # Make sure we don't try and use uwsgi protocol 'protocol': 'http', # Make sure we reload really quickly for local dev in case it # doesn't want to shut down nicely on it's own, NO MERCY 'worker-reload-mercy': 2, # We need stdin to support pdb in devserver 'honour-stdin': True, # accept ridiculously large files 'limit-post': 1 << 30, # do something with chunked 'http-chunked-input': True, } if reload: uwsgi_overrides['py-autoreload'] = 1 daemons = [] if watchers and not browser_reload: daemons += settings.SENTRY_WATCHERS # For javascript dev, if browser reload and watchers, then: # devserver listen on PORT + 1 # webpack dev server listen on PORT + 2 # proxy listen on PORT if watchers and browser_reload: new_port = port + 1 os.environ['WEBPACK_DEV_PROXY'] = '%s' % port os.environ['WEBPACK_DEV_PORT'] = '%s' % (new_port + 1) os.environ['SENTRY_DEVSERVER_PORT'] = '%s' % new_port port = new_port daemons += [('jsproxy', ['yarn', 'dev-proxy']), ('webpack', ['yarn', 'dev-server'])] if workers: if settings.CELERY_ALWAYS_EAGER: raise click.ClickException( 'Disable CELERY_ALWAYS_EAGER in your settings file to spawn workers.' ) daemons += [ ('worker', ['sentry', 'run', 'worker', '-c', '1', '--autoreload']), ('cron', ['sentry', 'run', 'cron', '--autoreload']), ] if needs_https and has_https: https_port = six.text_type(parsed_url.port) https_host = parsed_url.hostname # Determine a random port for the backend http server import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((host, 0)) port = s.getsockname()[1] s.close() bind = '%s:%d' % (host, port) daemons += [ ('https', [ 'https', '-host', https_host, '-listen', host + ':' + https_port, bind ]), ] # A better log-format for local dev when running through honcho, # but if there aren't any other daemons, we don't want to override. if daemons: uwsgi_overrides[ 'log-format'] = '"%(method) %(uri) %(proto)" %(status) %(size)' else: uwsgi_overrides[ 'log-format'] = '[%(ltime)] "%(method) %(uri) %(proto)" %(status) %(size)' server = SentryHTTPServer(host=host, port=port, workers=1, extra_options=uwsgi_overrides) # If we don't need any other daemons, just launch a normal uwsgi webserver # and avoid dealing with subprocesses if not daemons: return server.run() import sys from subprocess import list2cmdline from honcho.manager import Manager from honcho.printer import Printer os.environ['PYTHONUNBUFFERED'] = 'true' # Make sure that the environment is prepared before honcho takes over # This sets all the appropriate uwsgi env vars, etc server.prepare_environment() daemons += [ ('server', ['sentry', 'run', 'web']), ] if styleguide: daemons += [('storybook', ['yarn', 'storybook'])] cwd = os.path.realpath( os.path.join(settings.PROJECT_ROOT, os.pardir, os.pardir)) manager = Manager(Printer(prefix=prefix)) for name, cmd in daemons: manager.add_process( name, list2cmdline(cmd), quiet=False, cwd=cwd, ) manager.loop() sys.exit(manager.returncode)
def devserver( reload, watchers, workers, ingest, experimental_spa, styleguide, prefix, pretty, environment, debug_server, bind, ): "Starts a lightweight web server for development." if bind is None: bind = "127.0.0.1:8000" if ":" in bind: host, port = bind.split(":", 1) port = int(port) else: host = bind port = None import os os.environ["SENTRY_ENVIRONMENT"] = environment # NODE_ENV *must* use production for any prod-like environment as third party libraries look # for this magic constant os.environ["NODE_ENV"] = "production" if environment.startswith( "prod") else environment from django.conf import settings from sentry import options from sentry.services.http import SentryHTTPServer url_prefix = options.get("system.url-prefix", "") parsed_url = urlparse(url_prefix) # Make sure we're trying to use a port that we can actually bind to needs_https = parsed_url.scheme == "https" and (parsed_url.port or 443) > 1024 has_https = False if needs_https: from subprocess import check_output try: check_output(["which", "https"]) has_https = True except Exception: has_https = False from sentry.runner.initializer import show_big_error show_big_error([ "missing `https` on your `$PATH`, but https is needed", "`$ brew install mattrobenolt/stuff/https`", ]) uwsgi_overrides = { "http-keepalive": True, # Make sure we reload really quickly for local dev in case it # doesn't want to shut down nicely on it's own, NO MERCY "worker-reload-mercy": 2, # We need stdin to support pdb in devserver "honour-stdin": True, # accept ridiculously large files "limit-post": 1 << 30, # do something with chunked "http-chunked-input": True, "thunder-lock": False, "timeout": 600, "harakiri": 600, } if reload: uwsgi_overrides["py-autoreload"] = 1 daemons = [] if experimental_spa: os.environ["SENTRY_UI_DEV_ONLY"] = "1" if not watchers: click.secho( "Using experimental SPA mode without watchers enabled has no effect", err=True, fg="yellow", ) # We proxy all requests through webpacks devserver on the configured port. # The backend is served on port+1 and is proxied via the webpack # configuration. if watchers: daemons += settings.SENTRY_WATCHERS proxy_port = port port = port + 1 uwsgi_overrides["protocol"] = "http" os.environ["FORCE_WEBPACK_DEV_SERVER"] = "1" os.environ["SENTRY_WEBPACK_PROXY_HOST"] = "%s" % host os.environ["SENTRY_WEBPACK_PROXY_PORT"] = "%s" % proxy_port os.environ["SENTRY_BACKEND_PORT"] = "%s" % port # webpack and/or typescript is causing memory issues os.environ["NODE_OPTIONS"] = (os.environ.get("NODE_OPTIONS", "") + " --max-old-space-size=4096").lstrip() else: # If we are the bare http server, use the http option with uwsgi protocol # See https://uwsgi-docs.readthedocs.io/en/latest/HTTP.html uwsgi_overrides.update({ # Make sure uWSGI spawns an HTTP server for us as we don't # have a proxy/load-balancer in front in dev mode. "http": f"{host}:{port}", "protocol": "uwsgi", # This is needed to prevent https://git.io/fj7Lw "uwsgi-socket": None, }) if ingest in (True, False): settings.SENTRY_USE_RELAY = ingest os.environ["SENTRY_USE_RELAY"] = "1" if settings.SENTRY_USE_RELAY else "" if workers: if settings.CELERY_ALWAYS_EAGER: raise click.ClickException( "Disable CELERY_ALWAYS_EAGER in your settings file to spawn workers." ) daemons += [_get_daemon("worker"), _get_daemon("cron")] from sentry import eventstream if eventstream.requires_post_process_forwarder(): daemons += [_get_daemon("post-process-forwarder")] if settings.SENTRY_EXTRA_WORKERS: daemons.extend( [_get_daemon(name) for name in settings.SENTRY_EXTRA_WORKERS]) if settings.SENTRY_DEV_PROCESS_SUBSCRIPTIONS: if not settings.SENTRY_EVENTSTREAM == "sentry.eventstream.kafka.KafkaEventStream": raise click.ClickException( "`SENTRY_DEV_PROCESS_SUBSCRIPTIONS` can only be used when " "`SENTRY_EVENTSTREAM=sentry.eventstream.kafka.KafkaEventStream`." ) for name, topic in settings.KAFKA_SUBSCRIPTION_RESULT_TOPICS.items( ): daemons += [ _get_daemon("subscription-consumer", "--topic", topic, suffix=name) ] if settings.SENTRY_USE_METRICS_DEV and settings.SENTRY_USE_RELAY: if not settings.SENTRY_EVENTSTREAM == "sentry.eventstream.kafka.KafkaEventStream": # The metrics indexer produces directly to kafka, so it makes # no sense to run it with SnubaEventStream. raise click.ClickException( "`SENTRY_USE_METRICS_DEV` can only be used when " "`SENTRY_EVENTSTREAM=sentry.eventstream.kafka.KafkaEventStream`." ) daemons += [_get_daemon("metrics")] if settings.SENTRY_USE_RELAY: daemons += [_get_daemon("ingest")] if needs_https and has_https: https_port = str(parsed_url.port) https_host = parsed_url.hostname # Determine a random port for the backend http server import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((host, 0)) port = s.getsockname()[1] s.close() bind = "%s:%d" % (host, port) daemons += [("https", [ "https", "-host", https_host, "-listen", host + ":" + https_port, bind ])] from sentry.runner.commands.devservices import _prepare_containers for name, container_options in _prepare_containers("sentry", silent=True).items(): if container_options.get("with_devserver", False): daemons += [(name, ["sentry", "devservices", "attach", "--fast", name])] # A better log-format for local dev when running through honcho, # but if there aren't any other daemons, we don't want to override. if daemons: uwsgi_overrides[ "log-format"] = "%(method) %(status) %(uri) %(proto) %(size)" else: uwsgi_overrides[ "log-format"] = "[%(ltime)] %(method) %(status) %(uri) %(proto) %(size)" server = SentryHTTPServer(host=host, port=port, workers=1, extra_options=uwsgi_overrides, debug=debug_server) # If we don't need any other daemons, just launch a normal uwsgi webserver # and avoid dealing with subprocesses if not daemons: return server.run() import sys from subprocess import list2cmdline from honcho.manager import Manager from honcho.printer import Printer os.environ["PYTHONUNBUFFERED"] = "true" if debug_server: threading.Thread(target=server.run).start() else: # Make sure that the environment is prepared before honcho takes over # This sets all the appropriate uwsgi env vars, etc server.prepare_environment() daemons += [_get_daemon("server")] if styleguide: daemons += [_get_daemon("storybook")] cwd = os.path.realpath( os.path.join(settings.PROJECT_ROOT, os.pardir, os.pardir)) honcho_printer = Printer(prefix=prefix) if pretty: from sentry.runner.formatting import monkeypatch_honcho_write honcho_printer.write = types.MethodType(monkeypatch_honcho_write, honcho_printer) manager = Manager(honcho_printer) for name, cmd in daemons: manager.add_process(name, list2cmdline(cmd), quiet=False, cwd=cwd) manager.loop() sys.exit(manager.returncode)
def devserver(reload, watchers, workers, experimental_spa, styleguide, prefix, environment, bind): "Starts a lightweight web server for development." if ":" in bind: host, port = bind.split(":", 1) port = int(port) else: host = bind port = None import os os.environ["SENTRY_ENVIRONMENT"] = environment from django.conf import settings from sentry import options from sentry.services.http import SentryHTTPServer url_prefix = options.get("system.url-prefix", "") parsed_url = urlparse(url_prefix) # Make sure we're trying to use a port that we can actually bind to needs_https = parsed_url.scheme == "https" and (parsed_url.port or 443) > 1024 has_https = False if needs_https: from subprocess import check_output try: check_output(["which", "https"]) has_https = True except Exception: has_https = False from sentry.runner.initializer import show_big_error show_big_error([ "missing `https` on your `$PATH`, but https is needed", "`$ brew install mattrobenolt/stuff/https`", ]) uwsgi_overrides = { 'http-keepalive': True, # Make sure we reload really quickly for local dev in case it # doesn't want to shut down nicely on it's own, NO MERCY "worker-reload-mercy": 2, # We need stdin to support pdb in devserver "honour-stdin": True, # accept ridiculously large files "limit-post": 1 << 30, # do something with chunked "http-chunked-input": True, "thunder-lock": False, "timeout": 600, "harakiri": 600, } if reload: uwsgi_overrides["py-autoreload"] = 1 daemons = [] if experimental_spa: os.environ["SENTRY_EXPERIMENTAL_SPA"] = "1" if not watchers: click.secho( "Using experimental SPA mode without watchers enabled has no effect", err=True, fg="yellow", ) # We proxy all requests through webpacks devserver on the configured port. # The backend is served on port+1 and is proxied via the webpack # configuration. if watchers: daemons += settings.SENTRY_WATCHERS proxy_port = port port = port + 1 uwsgi_overrides['protocol'] = 'http' os.environ["SENTRY_WEBPACK_PROXY_PORT"] = "%s" % proxy_port os.environ["SENTRY_BACKEND_PORT"] = "%s" % port # Replace the webpack watcher with the drop-in webpack-dev-server webpack_config = next(w for w in daemons if w[0] == "webpack")[1] webpack_config[0] = os.path.join( *os.path.split(webpack_config[0])[0:-1] + ("webpack-dev-server", )) daemons = [w for w in daemons if w[0] != "webpack" ] + [("webpack", webpack_config)] else: # If we are the bare http server, use the http option with uwsgi protocol # See https://uwsgi-docs.readthedocs.io/en/latest/HTTP.html uwsgi_overrides.update({ # Make sure uWSGI spawns an HTTP server for us as we don't # have a proxy/load-balancer in front in dev mode. 'http': '%s:%s' % (host, port), 'protocol': 'uwsgi', # This is needed to prevent https://git.io/fj7Lw 'uwsgi-socket': None, }) if workers: if settings.CELERY_ALWAYS_EAGER: raise click.ClickException( "Disable CELERY_ALWAYS_EAGER in your settings file to spawn workers." ) daemons += [ ("worker", ["sentry", "run", "worker", "-c", "1", "--autoreload"]), ("cron", ["sentry", "run", "cron", "--autoreload"]), ] from sentry import eventstream if eventstream.requires_post_process_forwarder(): daemons += [( "relay", [ "sentry", "run", "post-process-forwarder", "--loglevel=debug", "--commit-batch-size=1", ], )] if needs_https and has_https: https_port = six.text_type(parsed_url.port) https_host = parsed_url.hostname # Determine a random port for the backend http server import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((host, 0)) port = s.getsockname()[1] s.close() bind = "%s:%d" % (host, port) daemons += [("https", [ "https", "-host", https_host, "-listen", host + ":" + https_port, bind ])] # A better log-format for local dev when running through honcho, # but if there aren't any other daemons, we don't want to override. if daemons: uwsgi_overrides[ "log-format"] = '"%(method) %(uri) %(proto)" %(status) %(size)' else: uwsgi_overrides[ "log-format"] = '[%(ltime)] "%(method) %(uri) %(proto)" %(status) %(size)' server = SentryHTTPServer(host=host, port=port, workers=1, extra_options=uwsgi_overrides) # If we don't need any other daemons, just launch a normal uwsgi webserver # and avoid dealing with subprocesses if not daemons: return server.run() import sys from subprocess import list2cmdline from honcho.manager import Manager from honcho.printer import Printer os.environ["PYTHONUNBUFFERED"] = "true" # Make sure that the environment is prepared before honcho takes over # This sets all the appropriate uwsgi env vars, etc server.prepare_environment() daemons += [("server", ["sentry", "run", "web"])] if styleguide: daemons += [("storybook", ["./bin/yarn", "storybook"])] cwd = os.path.realpath( os.path.join(settings.PROJECT_ROOT, os.pardir, os.pardir)) manager = Manager(Printer(prefix=prefix)) for name, cmd in daemons: manager.add_process(name, list2cmdline(cmd), quiet=False, cwd=cwd) manager.loop() sys.exit(manager.returncode)
def devserver(reload, watchers, workers, browser_reload, styleguide, prefix, environment, bind): "Starts a lightweight web server for development." if ':' in bind: host, port = bind.split(':', 1) port = int(port) else: host = bind port = None import os os.environ['SENTRY_ENVIRONMENT'] = environment from django.conf import settings from sentry import options from sentry.services.http import SentryHTTPServer url_prefix = options.get('system.url-prefix', '') parsed_url = urlparse(url_prefix) # Make sure we're trying to use a port that we can actually bind to needs_https = ( parsed_url.scheme == 'https' and (parsed_url.port or 443) > 1024 ) has_https = False if needs_https: from subprocess import check_output try: check_output(['which', 'https']) has_https = True except Exception: has_https = False from sentry.runner.initializer import show_big_error show_big_error( [ 'missing `https` on your `$PATH`, but https is needed', '`$ brew install mattrobenolt/stuff/https`', ] ) uwsgi_overrides = { # Make sure we don't try and use uwsgi protocol 'protocol': 'http', # Make sure we reload really quickly for local dev in case it # doesn't want to shut down nicely on it's own, NO MERCY 'worker-reload-mercy': 2, # We need stdin to support pdb in devserver 'honour-stdin': True, # accept ridiculously large files 'limit-post': 1 << 30, # do something with chunked 'http-chunked-input': True, 'thunder-lock': False, 'timeout': 600, 'harakiri': 600, } if reload: uwsgi_overrides['py-autoreload'] = 1 daemons = [] if watchers: daemons += settings.SENTRY_WATCHERS # When using browser_reload we proxy all requests through webpacks # devserver on the configured port. The backend is served on port+1 and is # proxied via the webpack configuration. if watchers and browser_reload: proxy_port = port port = port + 1 os.environ['SENTRY_WEBPACK_PROXY_PORT'] = '%s' % proxy_port os.environ['SENTRY_BACKEND_PORT'] = '%s' % port # Replace the webpack watcher with the drop-in webpack-dev-server webpack_config = next(w for w in daemons if w[0] == 'webpack')[1] webpack_config[0] = os.path.join( *os.path.split(webpack_config[0])[0:-1] + ('webpack-dev-server', ) ) daemons = [w for w in daemons if w[0] != 'webpack'] + [ ('webpack', webpack_config), ] if workers: if settings.CELERY_ALWAYS_EAGER: raise click.ClickException( 'Disable CELERY_ALWAYS_EAGER in your settings file to spawn workers.' ) daemons += [ ('worker', ['sentry', 'run', 'worker', '-c', '1', '--autoreload']), ('cron', ['sentry', 'run', 'cron', '--autoreload']), ] from sentry import eventstream if eventstream.requires_post_process_forwarder(): daemons += [ ('relay', ['sentry', 'run', 'post-process-forwarder', '--loglevel=debug', '--commit-batch-size=1']), ] if needs_https and has_https: https_port = six.text_type(parsed_url.port) https_host = parsed_url.hostname # Determine a random port for the backend http server import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((host, 0)) port = s.getsockname()[1] s.close() bind = '%s:%d' % (host, port) daemons += [ ('https', ['https', '-host', https_host, '-listen', host + ':' + https_port, bind]), ] # A better log-format for local dev when running through honcho, # but if there aren't any other daemons, we don't want to override. if daemons: uwsgi_overrides['log-format'] = '"%(method) %(uri) %(proto)" %(status) %(size)' else: uwsgi_overrides['log-format'] = '[%(ltime)] "%(method) %(uri) %(proto)" %(status) %(size)' server = SentryHTTPServer(host=host, port=port, workers=1, extra_options=uwsgi_overrides) # If we don't need any other daemons, just launch a normal uwsgi webserver # and avoid dealing with subprocesses if not daemons: return server.run() import sys from subprocess import list2cmdline from honcho.manager import Manager from honcho.printer import Printer os.environ['PYTHONUNBUFFERED'] = 'true' # Make sure that the environment is prepared before honcho takes over # This sets all the appropriate uwsgi env vars, etc server.prepare_environment() daemons += [ ('server', ['sentry', 'run', 'web']), ] if styleguide: daemons += [('storybook', ['yarn', 'storybook'])] cwd = os.path.realpath(os.path.join(settings.PROJECT_ROOT, os.pardir, os.pardir)) manager = Manager(Printer(prefix=prefix)) for name, cmd in daemons: manager.add_process( name, list2cmdline(cmd), quiet=False, cwd=cwd, ) manager.loop() sys.exit(manager.returncode)
def devserver(reload, watchers, workers, experimental_spa, styleguide, prefix, environment, bind): "Starts a lightweight web server for development." if ':' in bind: host, port = bind.split(':', 1) port = int(port) else: host = bind port = None import os os.environ['SENTRY_ENVIRONMENT'] = environment from django.conf import settings from sentry import options from sentry.services.http import SentryHTTPServer url_prefix = options.get('system.url-prefix', '') parsed_url = urlparse(url_prefix) # Make sure we're trying to use a port that we can actually bind to needs_https = (parsed_url.scheme == 'https' and (parsed_url.port or 443) > 1024) has_https = False if needs_https: from subprocess import check_output try: check_output(['which', 'https']) has_https = True except Exception: has_https = False from sentry.runner.initializer import show_big_error show_big_error([ 'missing `https` on your `$PATH`, but https is needed', '`$ brew install mattrobenolt/stuff/https`', ]) uwsgi_overrides = { # Make sure we don't try and use uwsgi protocol 'protocol': 'http', # Make sure we reload really quickly for local dev in case it # doesn't want to shut down nicely on it's own, NO MERCY 'worker-reload-mercy': 2, # We need stdin to support pdb in devserver 'honour-stdin': True, # accept ridiculously large files 'limit-post': 1 << 30, # do something with chunked 'http-chunked-input': True, 'thunder-lock': False, 'timeout': 600, 'harakiri': 600, } if reload: uwsgi_overrides['py-autoreload'] = 1 daemons = [] if experimental_spa: os.environ['SENTRY_EXPERIMENTAL_SPA'] = '1' if not watchers: click.secho( 'Using experimental SPA mode without watchers enabled has no effect', err=True, fg='yellow') # We proxy all requests through webpacks devserver on the configured port. # The backend is served on port+1 and is proxied via the webpack # configuration. if watchers: daemons += settings.SENTRY_WATCHERS proxy_port = port port = port + 1 os.environ['SENTRY_WEBPACK_PROXY_PORT'] = '%s' % proxy_port os.environ['SENTRY_BACKEND_PORT'] = '%s' % port # Replace the webpack watcher with the drop-in webpack-dev-server webpack_config = next(w for w in daemons if w[0] == 'webpack')[1] webpack_config[0] = os.path.join( *os.path.split(webpack_config[0])[0:-1] + ('webpack-dev-server', )) daemons = [w for w in daemons if w[0] != 'webpack'] + [ ('webpack', webpack_config), ] if workers: if settings.CELERY_ALWAYS_EAGER: raise click.ClickException( 'Disable CELERY_ALWAYS_EAGER in your settings file to spawn workers.' ) daemons += [ ('worker', ['sentry', 'run', 'worker', '-c', '1', '--autoreload']), ('cron', ['sentry', 'run', 'cron', '--autoreload']), ] from sentry import eventstream if eventstream.requires_post_process_forwarder(): daemons += [ ('relay', [ 'sentry', 'run', 'post-process-forwarder', '--loglevel=debug', '--commit-batch-size=1' ]), ] if needs_https and has_https: https_port = six.text_type(parsed_url.port) https_host = parsed_url.hostname # Determine a random port for the backend http server import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((host, 0)) port = s.getsockname()[1] s.close() bind = '%s:%d' % (host, port) daemons += [ ('https', [ 'https', '-host', https_host, '-listen', host + ':' + https_port, bind ]), ] # A better log-format for local dev when running through honcho, # but if there aren't any other daemons, we don't want to override. if daemons: uwsgi_overrides[ 'log-format'] = '"%(method) %(uri) %(proto)" %(status) %(size)' else: uwsgi_overrides[ 'log-format'] = '[%(ltime)] "%(method) %(uri) %(proto)" %(status) %(size)' server = SentryHTTPServer(host=host, port=port, workers=1, extra_options=uwsgi_overrides) # If we don't need any other daemons, just launch a normal uwsgi webserver # and avoid dealing with subprocesses if not daemons: return server.run() import sys from subprocess import list2cmdline from honcho.manager import Manager from honcho.printer import Printer os.environ['PYTHONUNBUFFERED'] = 'true' # Make sure that the environment is prepared before honcho takes over # This sets all the appropriate uwsgi env vars, etc server.prepare_environment() daemons += [ ('server', ['sentry', 'run', 'web']), ] if styleguide: daemons += [('storybook', ['./bin/yarn', 'storybook'])] cwd = os.path.realpath( os.path.join(settings.PROJECT_ROOT, os.pardir, os.pardir)) manager = Manager(Printer(prefix=prefix)) for name, cmd in daemons: manager.add_process( name, list2cmdline(cmd), quiet=False, cwd=cwd, ) manager.loop() sys.exit(manager.returncode)