Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add --profile flag to enable simpler debug profiling #393

Merged
merged 1 commit into from
Apr 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,15 @@ RUN groupadd -g 51453 synse \
RUN apt-get update && apt-get install -y --no-install-recommends \
tini curl \
&& rm -rf /var/lib/apt/lists/* \
&& mkdir -p /synse \
&& mkdir -p /etc/synse \
&& chown -R synse:synse /synse \
&& chown -R synse:synse /etc/synse

COPY --from=builder /build /usr/local
COPY ./assets/favicon.ico /etc/synse/static/favicon.ico

USER synse
WORKDIR synse

ENTRYPOINT ["/usr/bin/tini", "--", "synse_server"]
35 changes: 34 additions & 1 deletion synse_server/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import argparse
import asyncio
import cProfile
import os
import sys

Expand Down Expand Up @@ -44,6 +45,10 @@ def main() -> None:
'--version', required=False, action='store_true',
help='print the version',
)
parser.add_argument(
'--profile', required=False, action='store_true',
help='profile synse server code execution,'
)
args = parser.parse_args()

if args.version:
Expand All @@ -54,7 +59,35 @@ def main() -> None:
host=args.host,
port=args.port,
)
server.run()

if args.profile:
print("""
*************************
Running in profiling mode
-------------------------
Synse Server was run with the --profile flag. This should only be used
for development/debug. It should not be used in production.

After Synse Server terminates, the profiling output will be printed out
to console and written to file (synse-server.profile). If running in a
container, it is your responsibility to copy the profile data out.
*************************
""")
pr = cProfile.Profile()
pr.enable()

try:
server.run()
except Exception as e:
print(f'Got exception: {e}')
finally:
pr.disable()

pr.print_stats('cumulative')
pr.dump_stats('synse-server.profile')

else:
server.run()


if __name__ == '__main__':
Expand Down
20 changes: 20 additions & 0 deletions synse_server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
"""

import asyncio
import functools
import os
import signal
import sys

from structlog import get_logger
Expand Down Expand Up @@ -118,6 +120,15 @@ def _initialize(self) -> None:

def run(self) -> None:
"""Run Synse Server."""

# Register signals for graceful termination
for sig in ('SIGINT', 'SIGTERM'):
logger.info('adding signal handler to synse loop')
loop.synse_loop.add_signal_handler(
sig=getattr(signal, sig),
callback=functools.partial(_handle_signal, sig, loop.synse_loop),
)

logger.info('running synse server')

# If we are configured to log the header, write it to stdout instead
Expand Down Expand Up @@ -202,3 +213,12 @@ def reload_config(self) -> None:
# Load and validate the configuration values.
config.options.parse(requires_cfg=False)
config.options.validate()


def _handle_signal(signame, loop):
"""Handler function for when the Synse loop receives a registered signal.

This indicates that the server should shut down gracefully.
"""
logger.info('received termination signal, stopping loop', signal=signame, loop=loop)
loop.stop()