Snippet
es una biblioteca extensible de Android para medir los tiempos de ejecución de secciones de código de una manera que no compromete la legibilidad y puede enviarse a producción sin ninguna configuración adicional. Puede agregar nuevos comportamientos a la biblioteca ampliando las rutas de ejecución. 2 rutas de ejecución proporcionadas con la biblioteca son:
MeasuredExecutionPath
– La ruta del código sobre la que se extiende el código de medición.ReleaseExecutionPath
– Una ruta sin operación (ruta predeterminada) que generalmente se instala en las variantes de lanzamiento.
- Fácil de integrar y configurar
- Cambia el comportamiento según el tipo de compilación.
- Reduce la placa de la caldera
- Reutilización de datos
- Hace que las revisiones de relaciones públicas sean más cuantitativas
- Impacto en el tamaño del APK de 23 KB
- Diseñado para ser seguro para subprocesos y nulos
- API enriquecida
- Completamente documentado, simplemente ejecute java docs.
- Atrapar : Intervalo lógico del código. Puede ser contiguo o no contiguo.
- Divisiones : Secciones de código en captura b / wa, miden el delta desde la última subdivisión.
- Token de registro : Realiza un seguimiento de las adquisiciones no contiguas.
- Camino de ejecución : Una abstracción para enrutar la ejecución dentro de la biblioteca. Se pueden escribir rutas personalizadas para una funcionalidad de usuario adicional y se pueden instalar en diferentes versiones de compilación.
- Bloquear hilos : El hilo que inicia la medición debe terminarlo.
Configuración en 3 sencillos pasos:
- Instale el deseado
ExecutionPath
, En elonCreate
de su clase de aplicación lo antes posible. Antes de estoSnippet
Las API no tendrán ningún efecto, ya que el fragmento viene con la ruta de ejecución predeterminada, que es la ruta sin operaciones. Para usos habitualesMeasuredExecutionPath
- Configure el filtro que desea usar en el log cat usando
newFilter
método, el filtro predeterminado es “Fragmento“ - Establezca indicadores que determinen la cantidad de detalles en los registros usando
addFlag
método. Las banderas admitidas por Snippet son,FLAG_METADATA_CLASS
,FLAG_METADATA_METHOD
,FLAG_METADATA_LINE
,FLAG_METADATA_THREAD_INFO
. Algunos de los filtros se agregan de forma predeterminada.
A continuación se muestra el código de instalación de ejemplo:
if(BuildConfig.DEBUG) {
Snippet.install(new Snippet.MeasuredExecutionPath());
Snippet.newFilter("SampleFilter");
Snippet.addFlag(Snippet.FLAG_METADATA_LINE | Snippet.FLAG_METADATA_THREAD_INFO);
}
Cómo medir un fragmento de código.
Hay 3 formas de adquirir la ruta del código.
-
Snippet.capture(Closure closure)
– Para la sección continua del código, pase el código como lambda dentro del cierre. -
Snippet.startCapture()/LogToken.endCapture()
– Para secciones de código no contiguas posiblemente dentro del mismo archivo. O lugares dondecapture(closure)
no funciona como lo hacen algunas clases internas anónimas. -
Snippet.startCapture(String tag)/Snippet.find(tag).endCapture()
– Para flujos de código que se extienden
varios archivos. anterior. comenzaste una medición enApplication.onCreate()
y acaba
medición de la actividad de aterrizaje. UsarSnippet.startCapture(tag)
para iniciar la medición e
encuentra el token usandoSnippet.find(tag)
y llamaendCapture()
en ese.
Caso de uso 1: Código que se puede pasar como lambda.
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
// The capture API can be used to measure the code that can be passed as a lambda.
// Adding this lambda captures the class, line, thread etc automatically into the logcat.
// This cannot be use for code that returns a value as the lambda declared for closure is
// is a non returning lambda. For the case that could return a value and are a little complex // use the log-token based API demonstrated below.
// Captures the code as a lambda.
Snippet.capture(()-> super.onCreate(savedInstanceState));
}
Caso de uso 2: La medición comienza en una clase diferente y termina en una
clase diferente. A continuación, la medición comenzó en la clase de Aplicación y terminará en una clase de Actividad. Usamos API basadas en TAG para manejar este caso.
public class SampleApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
if(BuildConfig.DEBUG) {
Snippet.install(new Snippet.MeasuredExecutionPath());
Snippet.newFilter("SampleFilter");
Snippet.addFlag(Snippet.FLAG_METADATA_LINE | Snippet.FLAG_METADATA_THREAD_INFO);
}
Snippet.startCapture("app_start"); // Start the measurement in Application class
}
}
y terminó en MainActivity
clase
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// End the measurement that started in the Application class
Snippet.find("app_start").endCapture();
}
@Override
protected void onStart() {
super.onStart();
}
}
Caso de uso 3: Usando tokens de registro. Los tokens de registro se pueden usar fácilmente dentro de una clase o método.
Si necesita utilizar tokens de registro para medir la propagación del código en varios archivos y las medidas no afectan a varios subprocesos, utilice la API basada en TAG descrita anteriormente.
LogToken brillará si necesita activar varios subprocesos al mismo tiempo y la medición está dentro del código común ejecutado por todos los subprocesos. Luego crea un token de registro separado y cambia a diferentes subprocesos. Estamos trabajando para corregir esta limitación.
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
// The capture API can be used to measure the code that can be passed as a lambda.
// Calling startCapture gives a log token to the caller that can we used to end the measurement.
// The moment start capture is called, the measurement has started and when end capture will
// be called on the log-token, that is when the measurement will end. Endcapture can be called only once
// per log token.
ILogToken token = Snippet.startCapture();
setContentView(R.layout.activity_main);
token.endCapture("Time to set the content view");
}
El fragmento captura toda la información de contexto como clase, método, hilo, número de línea fuera de la caja y crea buenos registros como se muestra a continuación. Para que pueda localizar fácilmente sus registros. Además, si necesita más verbosidad, cada API también tiene una sobrecarga basada en cadenas. También puedes explorar eso.
2021-12-11 15:11:24.197 11400-11400/com.microsoft.sample D/SampleFilter: [Class = MainActivity]|::::|[Method = onCreate]|::::|<Line no. 21>|::::|[Thread name = main]|::::||::::|(18 ms)
2021-12-11 15:11:24.376 11400-11400/com.microsoft.sample D/SampleFilter: Time to set the content view|::::|[Class = MainActivity]|::::|[Method = onCreate]|::::|<Line no. 29>|::::|[Thread name = main]|::::||::::|(178 ms)
2021-12-11 15:11:24.377 11400-11400/com.microsoft.sample D/SampleFilter: [Class = MainActivity]|::::|[Method = onCreate]|::::|<Line no. 32>|::::|[Thread name = main]|::::||::::|(295 ms)
Podemos crear múltiples implementaciones de rutas de ejecución extendiendo las clases MeasuredExecutionPath y hacer un trabajo personalizado con los datos proporcionados por la ruta medida, como registrarlos en servidores remotos, poner todos los datos en una base de datos, archivo, etc. FileExecutionPath
en la aplicación de muestra.
Consulte la aplicación de muestra en app/
para ver el proceso en acción.
Divisiones
Divisiones se puede definir como un rango lógico de código dentro de una adquisición. Las divisiones pueden extenderse dentro del mismo archivo o en diferentes archivos. El objetivo es duplicar las áreas enfocadas y ayudar con la depuración.
Podría usarse para ver qué contribuye una pequeña parte de código a la adquisición y búsqueda de un área problemática.
Le recomendamos que utilice siempre divisiones solo con fines de depuración. No se recomienda enviar el código relacionado con las divisiones a producción. A continuación se muestra la demostración sobre cómo usar las divisiones
- Una vez que haya obtenido un token de registro usando
Snippet.startCapture()
llamar. - Puedes llamar
logtoken.addSplit()
llamar. Imprimirá el tiempo transcurrido desde entonces
la última llamada aaddSplit()
se ha hecho o si es una primera vuelta medirá el tiempo
de la llamada astartCapture().
- No hay límite para el número de divisiones que se pueden crear una vez
endCapture()
se llama,
fragmento de impresiones un “Resumen dividido” que muestra el porcentaje de tiempo que tomó cada división
con respecto a la captura.
Haga clic en Me gusta a continuación para ver cómo se ve el resumen dividido. ¿Cómo se ve el resumen dividido?
ThreadLock
El bloqueo de hilo es la funcionalidad donde el hilo que empezó a medir
utilizando startCapture()
solo podía terminar con eso. Si otro hilo intenta hacer esto, se registra un error y se omite la acción. Se puede habilitar fácilmente de esta manera
Snippet.startCapture (). EnableThreadLock ()
Caminos de ejecución
- La ruta de ejecución determina cómo debe comportarse la funcionalidad básica de esta biblioteca.
- Es posible que tampoco queramos ejecutar el código por completo en las compilaciones de lanzamiento.
- es posible que desee agregar información adicional a la información existente y agregarla a los archivos.
- Podemos vincular una ruta o método de ejecución personalizado a través de
Snippet.install(executionPath)
método.
El fragmento viene con un MeasuredExecutionPath
Y ReleaseExecutionPath
, la ruta medida es la que enruta las llamadas de la API de fragmentos a la funcionalidad de la biblioteca principal y ReleaseExecutionPath
hacer Snippet sin operación. La ruta de acceso es la ruta predeterminada para Snippet. El usuario debe establecer la ruta para tipos de compilación específicos usando Snippet.install(executionPath)
. A continuación se muestra un ejemplo, donde establecemos el MeasuredExecutionPath
en construir DEBUG y FileExecutionPath
en construir LIBERACIÓN.
if(BuildConfig.DEBUG) {
Snippet.install(new Snippet.MeasuredExecutionPath());
Snippet.newFilter("SampleFilter");
} else {
Snippet.install(new FileExecutionPath());
Snippet.newFilter("ReleaseFilter");
}
Snippet.addFlag(Snippet.FLAG_METADATA_LINE | Snippet.FLAG_METADATA_THREAD_INFO);
Escribe una ruta de ejecución personalizada
-
Ampliar
ExecutionPath
, en nuestro ejemplo ampliaremosMeasuredExecutionPath
. -
Invadir
ExecutionPath#capture(Closure)
YExecutionPath#capture(String, Closure)
Esto asegurará que esté implementando código personalizado para la API basada en lambda. -
También debe proporcionar un token de registro personalizado y anular el
LogToken#endCapture()
YLogToken#endCapture(String)
para que pueda realizar acciones personalizadas en todos los tipos (contiguos / no contiguos) de código. -
Para hacer esto, extienda ExtendableLogToken y sobrescriba
ExtendableLogToken#endCapture(String)
,
YExtendableLogToken#endCapture()
. Una vez hecho esto, devuelva elExtendableLogToken
instancia deSnippet#startCapture(String)
, YSnippet#startCapture(String)
métodos.
NOTA: En casi todos los casos, cualquier nueva ruta de ejecución que se cree requeriría una nueva extensión de ExtendableLogToken
Muestra:
/**
* Demo for showing custom implementation of Execution Path. This path, takes the data that is * captured from the MeasuredExecutionPath and passes it to FileExecutionPath and then the data * is written to the file. * <p>
* We need to override LogToken also, as for the code that is non contiguous all the measurements * are inside the log token that is handed over to the user by Snippet.startCapture() API * So if we want that our new execution to work for both kinds of APIs that ie. * The one passed through a lambda in Snippet.capture(lambda) and Snippet.startCapture()/LogToken.endCapture()
* We need to override both the classes. */
public class FileExecutionPath extends Snippet.MeasuredExecutionPath {
@Override
public ILogToken startCapture(String tag) {
return super.startCapture(tag);
}
@NonNull
@Override
public ExecutionContext capture(String message, Snippet.Closure closure) {
ExecutionContext context = super.capture(message, closure);
Log.d("Snippet", "Class: " + context.getClassName() + "Duration: " + context.getExecutionDuration());
// Context has all the information that measured path has captured. Use that to write to files.
return writeToFile(context);
}
private ExecutionContext writeToFile(ExecutionContext context) {
// Code to write to a file goes here, create a thread and write.
// Finally return a the execution context(could be the same or a new implementation) with some // of the details that you captured.
// NOTE: always put the relevant information on the context before you start doing IO // so that the execution path could return successfully.
return context;
}
@NonNull
@Override public ExecutionContext capture(Snippet.Closure closure) {
return super.capture(closure);
}
// We need to return a log token implementation that writes to a file when we call endCapture()
// APIs.
// USE ExtendableLogToken for the above purpose @Override
public ILogToken startCapture() {
return new ExtendableLogToken(super.startCapture());
}
@Override
public ILogToken find(String tag) {
return super.find(tag);
}
public class FileWritingLogToken extends ExtendableLogToken {
public FileWritingLogToken(ILogToken logToken) {
super(logToken);
}
@Override
public ExecutionContext endCapture(String message) {
ExecutionContext context = super.endCapture(message);
writeToFile(context);
return context;
}
@Override
public ExecutionContext endCapture() {
ExecutionContext context = super.endCapture();
writeToFile(context);
return context;
}
}
}
Finalmente, instálalo en la creación de la aplicación,
if(Build.DEBUG) {
Snippet.install(new FileExecutionContext());
}
Saludos,
Contribuir
Este proyecto agradece contribuciones y sugerencias. La mayoría de las contribuciones requieren que acepte un Acuerdo de licencia de colaborador (CLA) que indique que tiene el derecho, y de hecho lo tiene, de otorgarnos los derechos para utilizar su contribución. Para obtener más detalles, visite https://cla.opensource.microsoft.com.
Cuando envía una solicitud de extracción, un bot de CLA determinará automáticamente si necesita proporcionar un CLA y decorar el PR de manera adecuada (por ejemplo, verificación de estado, comentario). Simplemente siga las instrucciones dadas por el bot. Solo necesitará hacer esto una vez en todos los repositorios que usen nuestro CLA.
Este proyecto ha adoptado
el Código de conducta de código abierto de Microsoft. Para más información, ver
el Preguntas frecuentes sobre el código de conducta o póngase en contacto con opencode@microsoft.com para cualquier otra pregunta o comentario.
Marcas comerciales
Este diseño puede contener marcas comerciales o logotipos de proyectos, productos o servicios. Uso autorizado de
Las marcas comerciales o logotipos de Microsoft están sujetos y deben cumplir Marcas comerciales y pautas de marca de Microsoft.
El uso de marcas comerciales o logotipos de Microsoft en versiones modificadas de este proyecto no debe causar confusión.
o involucrar el patrocinio de Microsoft.
Cualquier uso de marcas comerciales o logotipos de terceros está sujeto a las políticas de esos terceros.
Descargar
Agréguelo en su build.gradle raíz al final de los repositorios:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
Agregue la dependencia a su proyecto y reemplace la etiqueta con la etiqueta de lanzamiento en el repositorio de git
dependencies {
implementation 'com.github.microsoft:snippet-timekeeper:Tag'
}
.