def CreateLogpoint(self, location, log_format_string, log_level=None, condition=None, user_email=None, labels=None): """Creates a logpoint in the debuggee. Args: location: The breakpoint source location, which will be interpreted by the debug agents on the machines running the Debuggee. Usually of the form file:line-number log_format_string: The message to log, optionally containin {expression}- style formatting. log_level: String (case-insensitive), one of 'info', 'warning', or 'error', indicating the log level that should be used for logging. condition: An optional conditional expression in the target's programming language. The snapshot will be taken when the expression is true. user_email: The email of the user who created the snapshot. labels: A dictionary containing key-value pairs which will be stored with the snapshot definition and reported when the snapshot is queried. Returns: The created Breakpoint message. Raises: InvalidLocationException: if location is empty or malformed. InvalidLogFormatException: if log_format is empty or malformed. """ if not location: raise errors.InvalidLocationException( 'The location must not be empty.') if not log_format_string: raise errors.InvalidLogFormatException( 'The log format string must not be empty.') labels_value = None if labels: labels_value = self._debug_messages.Breakpoint.LabelsValue( additionalProperties=[ self._debug_messages.Breakpoint.LabelsValue.AdditionalProperty( key=key, value=value) for key, value in six.iteritems(labels)]) location = self._LocationFromString(location) if log_level: log_level = ( self._debug_messages.Breakpoint.LogLevelValueValuesEnum( log_level.upper())) log_message_format, expressions = SplitLogExpressions(log_format_string) request = ( self._debug_messages. ClouddebuggerDebuggerDebuggeesBreakpointsSetRequest( debuggeeId=self.target_id, breakpoint=self._debug_messages.Breakpoint( location=location, condition=condition, logLevel=log_level, logMessageFormat=log_message_format, expressions=expressions, labels=labels_value, userEmail=user_email, action=(self._debug_messages.Breakpoint. ActionValueValuesEnum.LOG)), clientVersion=self.CLIENT_VERSION)) try: response = self._debug_client.debugger_debuggees_breakpoints.Set(request) except apitools_exceptions.HttpError as error: raise errors.UnknownHttpError(error) return self.AddTargetInfo(response.breakpoint)
def SplitLogExpressions(format_string): """Extracts {expression} substrings into a separate array. Each substring of the form {expression} will be extracted into an array, and each {expression} substring will be replaced with $N, where N is the index of the extraced expression in the array. For example, given the input: 'a={a}, b={b}' The return value would be: ('a=$0, b=$1', ['a', 'b']) Args: format_string: The string to process. Returns: string, [string] - The new format string and the array of expressions. Raises: InvalidLogFormatException: if the string has unbalanced braces. """ expressions = [] log_format = '' current_expression = '' brace_count = 0 need_separator = False for c in format_string: if need_separator and c.isdigit(): log_format += ' ' need_separator = False if c == '{': if brace_count: # Nested braces current_expression += c else: # New expression current_expression = '' brace_count += 1 elif brace_count: # Currently reading an expression. if c != '}': current_expression += c continue brace_count -= 1 if brace_count == 0: # Finish processing the expression if current_expression in expressions: i = expressions.index(current_expression) else: i = len(expressions) expressions.append(current_expression) log_format += '${0}'.format(i) # If the next character is a digit, we need an extra space to prevent # the agent from combining the positional argument with the subsequent # digits. need_separator = True else: # Closing a nested brace current_expression += c else: # Not in or starting an expression. log_format += c if brace_count: # Unbalanced left brace. raise errors.InvalidLogFormatException( 'There are too many "{" characters in the log format string') return log_format, expressions