File: //lib/google-cloud-sdk/lib/surface/debug/logpoints/create.py
# -*- coding: utf-8 -*- #
# Copyright 2016 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Create command for gcloud debug logpoints command group."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.debug import debug
from googlecloudsdk.calliope import base
from googlecloudsdk.core import log
from googlecloudsdk.core import properties
DETAILED_HELP = {
'brief':
"""\
Add debug logpoints to a Cloud Debugger debug target (debuggee).
""",
'DESCRIPTION':
"""\
*{command}* is used to add a debug logpoint to a debug target
(debuggee). Logpoints add logging to your running service without
changing your code or restarting your application. When you create a
logpoint, the message you specify will be added to your logs whenever
any instance of your service executes the specified line of code.
The default lifetime of a logpoint is 24 hours from creation, and the
output will go to the standard log for the programming language of the
target (``java.logging'' for Java, ``logging'' for Python, etc.)
""",
'EXAMPLES':
"""\
To add a logpoint with no conditions that will print the value of the
variable 'name' at line 41 of file main.py of a debug target (debuggee),
run:
$ {command} main.py:41 "Variable name={name}" --target=<debuggee_id>
To add a logpoint that will print the value of the variable 'name' at
line 41 of file main.py on a debug target (debuggee) that will only
trigger if the length of 'name' is greater than 3, run:
$ {command} main.py:41 "Variable name={name}" --target=<debuggee_id> --condition="len(name) > 3"
To add a logpoint with a log level of error at line 35 of file main.py
on a debug target (debuggee), run:
$ {command} main.py:35 "Unexpected path" --target=<debuggee_id> --log-level=error
"""
}
class Create(base.CreateCommand):
"""Create debug logpoints."""
detailed_help = DETAILED_HELP
@staticmethod
def Args(parser):
parser.add_argument(
'location',
help="""\
The logpoint location. Locations are of
the form FILE:LINE, where FILE can be simply the file name, or the
file name preceded by enough path components to differentiate it
from other files with the same name. It is an error to provide a
file name that is not unique in the debug target.
""")
parser.add_argument(
'log_format_string',
help="""\
A format string which will be logged every time the logpoint
location is executed. If the string contains curly braces ('{' and
'}'), any text within the curly braces will be interpreted as a
run-time expression in the debug target's language, which will be
evaluated when the logpoint is hit.
The value of the expression will then replace the {} expression in
the resulting log output. For example, if you specify the format
string "a={a}, b={b}", and the logpoint is hit when local variable
a is 1 and b is 2, the resulting log output would be "a=1, b=2".
""")
parser.add_argument(
'--condition',
help="""\
A condition to restrict when the log output is generated. When the
logpoint is hit, the condition will be evaluated, and the log output
will be generated only if the condition is true.
""")
parser.add_argument(
'--log-level', choices=['info', 'warning', 'error'],
default='info',
help='The logging level to use when producing the log message.')
parser.add_argument(
'--wait', default=10,
help="""\
The number of seconds to wait to ensure that no error is returned
from a debugger agent when creating the logpoint. When a logpoint
is created, there will be a delay before the agents see and apply
the logpoint. Until at least one agent has attempted to
enable the logpoint, it cannot be determined if the logpoint is
valid.
""")
parser.display_info.AddFormat("""
list(
format("id: {0}", id),
format("location: {0}", location),
format("logLevel: {0}", logLevel),
format("logMessageFormat: {0}", logMessageFormat),
format("condition: {0}", condition),
format("logViewUrl: {0}", logViewUrl),
format("status: {0}", full_status())
)
""")
def Run(self, args):
"""Run the create command."""
project_id = properties.VALUES.core.project.Get(required=True)
user_email = properties.VALUES.core.account.Get(required=True)
debugger = debug.Debugger(project_id)
debuggee = debugger.FindDebuggee(args.target)
logpoint = debuggee.CreateLogpoint(
location=args.location, log_level=args.log_level,
log_format_string=args.log_format_string, condition=args.condition,
user_email=user_email)
# Wait a short time to see if the logpoint generates an error. Ideally,
# we'd want to wait until we get a response that the logpoint was set
# by at least one instance, but the API does not currently support that.
final_logpoint = debuggee.WaitForBreakpointSet(logpoint.id, args.wait,
args.location)
if args.location != final_logpoint.location:
log.status.write(
'The debugger adjusted the logpoint location to {0}'.format(
final_logpoint.location))
return final_logpoint or logpoint