Skip to content

Commit

Permalink
Remove minutes log in PFS (#2172)
Browse files Browse the repository at this point in the history
Please add an informative description that covers that changes made by
the pull request and link all relevant issues.

- [ ] **The pull request does not introduce [breaking changes].**
- [ ] **CHANGELOG is updated for new features, bug fixes or other
significant changes.**
- [ ] **I have read the [contribution guidelines](../CONTRIBUTING.md).**
- [ ] **Create an issue and link to the pull request to get dedicated
review from promptflow team. Learn more: [suggested
workflow](../CONTRIBUTING.md#suggested-workflow).**

- [ ] Title of the pull request is clear and informative.
- [ ] There are a small number of commits, each of which have an
informative message. This means that previously merged commits do not
appear in the history of the PR. For more information on cleaning up the
commits in your PR, [see this
page](https://github.com/Azure/azure-powershell/blob/master/documentation/development-docs/cleaning-up-commits.md).

- [ ] Pull request includes test coverage for the included changes.

---------

Co-authored-by: Ying Chen <2601502859@qq.com>
  • Loading branch information
2 people authored and zhengfeiwang committed Mar 1, 2024
1 parent 0861876 commit 6b70248
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 23 deletions.
5 changes: 4 additions & 1 deletion .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,10 @@
"OTLP",
"spawnv",
"spawnve",
"addrs"
"addrs",
"pywin",
"STARTF",
"mltable"
],
"flagWords": [
"Prompt Flow"
Expand Down
3 changes: 0 additions & 3 deletions src/promptflow/promptflow/_sdk/_service/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,6 @@ def log_after_request_info(response):
def monitor_request():
while True:
time.sleep(PF_SERVICE_MONITOR_SECOND)
# For python scenario, since we start waitress in cli, there will be two app. The one used to log in
# the parent process will have no "last_request_time" in app.config since the app doesn't run.
app.logger.info(f"Promptflow service is running, version: {get_promptflow_sdk_version()}")
if "last_request_time" in app.config and datetime.now() - app.config["last_request_time"] > timedelta(
hours=PF_SERVICE_HOUR_TIMEOUT
):
Expand Down
67 changes: 48 additions & 19 deletions src/promptflow/promptflow/_sdk/_service/entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@
kill_service_get_from_original_port_file,
)
from promptflow._sdk._utils import get_promptflow_sdk_version, print_pf_version
from promptflow._utils.logger_utils import get_cli_sdk_logger # noqa: E402
from promptflow.exceptions import UserErrorException

app, _ = create_app()
logger = get_cli_sdk_logger()


def get_app(environ, start_response):
Expand Down Expand Up @@ -83,23 +84,21 @@ def add_show_status_action(subparsers):

def start_service(args):
# User Agent will be set based on header in request, so not set globally here.
global app
os.environ[PF_NO_INTERACTIVE_LOGIN] = "true"
port = args.port
if args.debug:
os.environ[PF_SERVICE_DEBUG] = "true"
app.logger.setLevel(logging.DEBUG)

# add this logic to stop pfs service which is start in the original port file.
kill_service_get_from_original_port_file()

def validate_port(port, force_start):
if is_port_in_use(port):
if force_start:
app.logger.warning(f"Force restart the service on the port {port}.")
logger.warning(f"Force restart the service on the port {port}.")
kill_exist_service(port)
else:
app.logger.warning(f"Service port {port} is used.")
logger.warning(f"Service port {port} is used.")
raise UserErrorException(f"Service port {port} is used.")

if port:
Expand All @@ -112,36 +111,66 @@ def validate_port(port, force_start):
if sys.executable.endswith("pfcli.exe"):
# For msi installer, use sdk api to start pfs since it's not supported to invoke waitress by cli directly
# after packaged by Pyinstaller.
app.logger.info(
f"Start Prompt Flow Service on http://localhost:{port}, version: {get_promptflow_sdk_version()}"
)
app, _ = create_app()
if os.environ.get(PF_SERVICE_DEBUG) == "true":
app.logger.setLevel(logging.DEBUG)
else:
app.logger.setLevel(logging.INFO)
print(f"Start Prompt Flow Service on http://localhost:{port}, version: {get_promptflow_sdk_version()}")
waitress.serve(app, host="127.0.0.1", port=port)
else:
# Note: in this scenario, we will have two app, one is the parent process created to log, one is created in
# the detached child process.
# Set host to localhost, only allow request from localhost.
cmd = ["waitress-serve", f"--listen=127.0.0.1:{port}", "promptflow._sdk._service.entry:get_app"]
# Start a pfs process using detach mode. It will start a new process and create a new app. So we use environment
# variable to pass the debug mode, since it will inherit parent process environment variable.
if platform.system() == "Windows":
subprocess.Popen(cmd, stdout=subprocess.DEVNULL, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
try:
import win32api
import win32con
import win32process
except ImportError as ex:
raise UserErrorException(
f"Please install pywin32 by 'pip install pywin32' and retry. prompt flow "
f"service start depends on pywin32.. {ex}"
)
command = f"waitress-serve --listen=127.0.0.1:{port} promptflow._sdk._service.entry:get_app"
startupinfo = win32process.STARTUPINFO()
startupinfo.dwFlags |= win32process.STARTF_USESHOWWINDOW
startupinfo.wShowWindow = win32con.SW_HIDE
process_attributes = None
thread_attributes = None
inherit_handles = False
creation_flags = win32con.CREATE_NEW_PROCESS_GROUP | win32con.DETACHED_PROCESS
environment = None
current_directory = None
process_handle, thread_handle, process_id, thread_id = win32process.CreateProcess(
None,
command,
process_attributes,
thread_attributes,
inherit_handles,
creation_flags,
environment,
current_directory,
startupinfo,
)

win32api.CloseHandle(process_handle)
win32api.CloseHandle(thread_handle)
else:
# Set host to localhost, only allow request from localhost.
cmd = ["waitress-serve", f"--listen=127.0.0.1:{port}", "promptflow._sdk._service.entry:get_app"]
subprocess.Popen(cmd, stdout=subprocess.DEVNULL, start_new_session=True)
is_healthy = check_pfs_service_status(port)
if is_healthy:
app.logger.info(
f"Start Prompt Flow Service on http://localhost:{port}, version: {get_promptflow_sdk_version()}"
)
print(f"Start Prompt Flow Service on http://localhost:{port}, version: {get_promptflow_sdk_version()}")
else:
app.logger.warning(f"Pfs service start failed in {port}.")
logger.warning(f"Pfs service start failed in {port}.")


def stop_service():
global app
port = get_port_from_config()
if port is not None:
kill_exist_service(port)
app.logger.info(f"Pfs service stop in {port}.")
print(f"Pfs service stop in {port}.")


def main():
Expand Down

0 comments on commit 6b70248

Please sign in to comment.