commands/FBCounterCommands.py (63 lines of code) (raw):
#!/usr/bin/python
# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
# These set of commands provide a way to use counters in debug time. By using these counters,
# you can track how many times your program takes a specific path.
#
# Sample Use Case:
# Let's say you have a function that logs some messages from various parts of your code.
# And you want to learn how many times logMessage is called on startup.
#
# 1. Add a breakpoint to the entry point of your program (e.g. main).
# a. Add `zzz 10 printcounter` as an action.
# b. Check "Automatically continue after evaluating actions"
# 2. Add a breakpoint to the logMessage function.
# a. Add `incrementcounter log` as an action.
# b. Add `incrementcounter log_{} message` as an action.
# c. Check "Automatically continue after evaluating actions"
# 3. Run the program
#
# Format String:
# It uses Python's string.Formatter to format strings. You can use placeholders here as you can in Python:
# https://docs.python.org/3.4/library/string.html#string.Formatter.format
#
# Sample key_format_string:
# "key_{}" (int)5 -> Will build the key string as "key_5"
# Can be removed when Python 2 support is removed.
from __future__ import print_function
import fbchisellldbbase as fb
counters = {}
def lldbcommands():
return [
FBIncrementCounterCommand(),
FBPrintCounterCommand(),
FBPrintCountersCommand(),
FBResetCounterCommand(),
FBResetCountersCommand(),
]
def generateKey(arguments):
keyFormatString = arguments[1]
keyArgs = []
for argument in arguments[2:]:
if argument.startswith("("):
value = fb.evaluateExpression(argument)
else:
value = fb.evaluateExpressionValue(argument).GetObjectDescription()
if not value:
value = fb.evaluateExpression(argument)
keyArgs.append(value)
return keyFormatString.format(*keyArgs).strip()
# Increments the counter for the key.
# (lldb) incrementcounter key_format_string key_args
class FBIncrementCounterCommand(fb.FBCommand):
def name(self):
return "incrementcounter"
def description(self):
return "Increments the counter for the key."
def run(self, arguments, options):
key = generateKey(arguments)
counters[key] = counters.get(key, 0) + 1
# Prints the counter for the key.
# (lldb) printcounter key_format_string key_args
# 0
class FBPrintCounterCommand(fb.FBCommand):
def name(self):
return "printcounter"
def description(self):
return "Prints the counter for the key."
def run(self, arguments, options):
key = generateKey(arguments)
print(str(counters[key]))
# Prints all the counters sorted by the keys.
# (lldb) printcounters
# key_1: 0
class FBPrintCountersCommand(fb.FBCommand):
def name(self):
return "printcounters"
def description(self):
return "Prints all the counters sorted by the keys."
def run(self, arguments, options):
keys = sorted(counters.keys())
for key in keys:
print(key + ": " + str(counters[key]))
# Resets the counter for the key.
# (lldb) resetcounter key_format_string key_args
class FBResetCounterCommand(fb.FBCommand):
def name(self):
return "resetcounter"
def description(self):
return "Resets the counter for the key."
def run(self, arguments, options):
key = generateKey(arguments)
counters[key] = 0
# Resets all the counters.
# (lldb) resetcounters
class FBResetCountersCommand(fb.FBCommand):
def name(self):
return "resetcounters"
def description(self):
return "Resets all the counters."
def run(self, arguments, options):
counters.clear()