Announcement

Collapse
No announcement yet.

Important Tech tip regarding Log files, ADB, Android Monitor, etc..

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Important Tech tip regarding Log files, ADB, Android Monitor, etc..

    Hi Everyone,

    When troubleshooting problems with your robot system, it is very helpful to use the log files to troubleshoot your system. It is also helpful to use real time debugging (with wireless ADB) to troubleshoot or tune your op modes. Unlike the telemetry messages, the log statements that you generate will stay in the log files and not disappear when the app is closed.

    I put together a quick document that describes how to access and review the log files on the FTC Robot Controller and FTC Driver Station. For now I have put the file on Google Drive at the following link:

    https://drive.google.com/open?id=0B0...25nbEpFSWpILW8

    In the future I might find a more permanent home to the document but for now (October 2015) please use the Google drive link above.

    I encourage members from our community to take a look at the document and learn how to capture and review the log files. This can be a very valuable tool for debugging and troubleshooting your system.

    Tom
    Last edited by JoAnn; 10-15-2015, 04:12 PM.

  • #2
    Originally posted by Tom Eng View Post
    Hi Everyone,

    When troubleshooting problems with your robot system, it is very helpful to use the log files to troubleshoot your system. It is also helpful to use real time debugging (with wireless ADB) to troubleshoot or tune your op modes. Unlike the telemetry messages, the log statements that you generate will stay in the log files and not disappear when the app is closed.

    I put together a quick document that describes how to access and review the log files on the FTC Robot Controller and FTC Driver Station. For now I have put the file on Google Drive at the following link:

    This can be a very valuable tool for debugging and troubleshooting your system.

    Tom
    Thanks Tom, great & helpful info, especially for us rookies that are still trying to find our footing. We haven't run into any major problems yet, but I'm sure once we dig into some more complicated opmodes this will certainly come in handy, and is already great as a teaching tool (errors or not)

    Thanks again!
    Michael P Clark
    Founding Mentor, FTC 9958
    http://www.redfishrobotics.com
    "We're Hooked on FIRST"

    Comment


    • #3
      Is there anyway to have the Robot Controller build a somewhat automated bug reports that gives Qualcomm/FIRST everything that they want at the tap of a team should a problem occur? I would say that it sould put the bug report somewhere where the user can access it, so they can manually submit it, for now.

      Comment


      • #4
        Originally posted by dmssargent View Post
        Is there anyway to have the Robot Controller build a somewhat automated bug reports that gives Qualcomm/FIRST everything that they want at the tap of a team should a problem occur? I would say that it sould put the bug report somewhere where the user can access it, so they can manually submit it, for now.
        The log file is viewable from the RC APP menu. It should not be oto difficult to add one of Android's "share with" activities to send it along. ( share will email ....). Y

        Comment


        • #5
          I have been using "wifi file transfer" application from Android Play Store. It gives a wireless access from any device with any browser. The user interface is like Windows Explorer allowing file transfers in both direction and management of files and folders; including deletions.



          After 2 months of usage, I don't have any complaints.

          Comment


          • #6
            I am still surprised that I have yet to here of FIRST/Qualcomm requesting of a memory dump and/or a thread dump.

            Comment


            • #7
              Originally posted by dmssargent View Post
              Is there anyway to have the Robot Controller build a somewhat automated bug reports that gives Qualcomm/FIRST everything that they want at the tap of a team should a problem occur? I would say that it sould put the bug report somewhere where the user can access it, so they can manually submit it, for now.
              Change com.qualcomm.ftccommon.ViewLogsActivity to include the following:

              "ViewLogsActivity" is currently called from the RC app's


              Code:
              Intent intent = new Intent(Intent.ACTION_SEND);
              intent.putExtra(Intent.EXTRA_SUBJECT, "Error Log reported");
              intent.putExtra(Intent.EXTRA_EMAIL, new String[]{ <email address>});
              intent.putExtra(Intent.EXTRA_TEXT, "Please see attached file);
              intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(<path to logfile>)));
              intent.setType("text/plain");

              Comment


              • #8
                Originally posted by dlevy View Post
                Change com.qualcomm.ftccommon.ViewLogsActivity to include the following:

                "ViewLogsActivity" is currently called from the RC app's


                Code:
                Intent intent = new Intent(Intent.ACTION_SEND);
                intent.putExtra(Intent.EXTRA_SUBJECT, "Error Log reported");
                intent.putExtra(Intent.EXTRA_EMAIL, new String[]{ <email address>});
                intent.putExtra(Intent.EXTRA_TEXT, "Please see attached file);
                intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(<path to logfile>)));
                intent.setType("text/plain");
                Wouldn't that intent require an email provider to be set up on the device? It may be better to write code that, in the onClick() on a button, posts the log to a pastebin with a reasonable API, and then shows the URL in a textview/popup dialog. Of course, it would need to be done asynchronously (no net on the UI thread)
                FTC6460 mentor (software+computer vision+electronics), FPGA enthusiast. In favor of allowing custom electronics on FTC bots.
                Co-founder of ##ftc live chat for FTC programming--currently you may need to join and wait some time for help--volunteer basis only.

                Comment


                • #9
                  Originally posted by hexafraction View Post
                  Wouldn't that intent require an email provider to be set up on the device? It may be better to write code that, in the onClick() on a button, posts the log to a pastebin with a reasonable API, and then shows the URL in a textview/popup dialog. Of course, it would need to be done asynchronously (no net on the UI thread)
                  I'd recommend that any Android phone use a default gmail account. They are free to create. I.e [email protected] or [email protected].
                  Having an email account on the phone comes in handy for other things too.

                  Comment


                  • #10
                    dlevy,
                    Excuse me for being dense, but I couldn't seem to find ViewLogsActivity.java in the standard ftc_app release source code base.
                    Please advise in more detail as to how to make the change you suggest.
                    Thanks,
                    Martin Haeberli
                    Mentor, Team 7593 TigerBots
                    ----
                    Originally posted by dlevy View Post
                    Change com.qualcomm.ftccommon.ViewLogsActivity to include the following:

                    "ViewLogsActivity" is currently called from the RC app's


                    Code:
                    Intent intent = new Intent(Intent.ACTION_SEND);
                    intent.putExtra(Intent.EXTRA_SUBJECT, "Error Log reported");
                    intent.putExtra(Intent.EXTRA_EMAIL, new String[]{ <email address>});
                    intent.putExtra(Intent.EXTRA_TEXT, "Please see attached file);
                    intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(<path to logfile>)));
                    intent.setType("text/plain");

                    Comment


                    • #11
                      Originally posted by mhaeberli View Post
                      dlevy,
                      Excuse me for being dense, but I couldn't seem to find ViewLogsActivity.java in the standard ftc_app release source code base.
                      Please advise in more detail as to how to make the change you suggest.
                      Thanks,
                      Martin Haeberli
                      Mentor, Team 7593 TigerBots
                      ----
                      You can't change the file, due to it being in a closed source library.

                      I wrote a quick OpMode to show basic diagnostics info:
                      public class Diag extends OpMode {
                      private static String TAG = "DIAGNOSITCS::";
                      @Override
                      public void init() {
                      String log = "Log:\n";
                      try {
                      Process logcat = Runtime.getRuntime().exec("logcat -d");
                      Thread.sleep(1000);
                      BufferedReader reader = new BufferedReader(new InputStreamReader(logcat.getInputStream()));

                      CharBuffer chars = CharBuffer.allocate(8192);
                      reader.read(chars);
                      log += chars.toString();
                      } catch (IOException e) {
                      Log.e(TAG, "Cannot start logcat monitor", e);
                      log += e.getLocalizedMessage();
                      } catch (InterruptedException e) {
                      return;
                      }

                      if (log.equals("Log:\n")) {
                      FileInputStream logcatFile = null;
                      try {
                      File file = new File("/sdcard/com.qualcomm.ftcrobotcontroller.logcat");
                      logcatFile = new FileInputStream(file);
                      InputStreamReader reader = new InputStreamReader(logcatFile);

                      char[] chars = new char[(int) file.length()];
                      reader.read(chars);
                      log += new String(chars);
                      } catch (IOException e) {
                      Log.e(TAG, e.getLocalizedMessage(), e);
                      }
                      }
                      String board = "Board: " + Build.BOARD +'\n';
                      String brand = "Brand: " + Build.BRAND +'\n';
                      String model = "Model No: " + Build.MODEL +'\n';
                      String serial = "RC Serial: " + Build.SERIAL +'\n';
                      String version = "Android Version: " + Build.VERSION.RELEASE +'\n';

                      String rcVersion;
                      try {
                      rcVersion = "RC Version: " + hardwareMap.appContext.getPackageManager().
                      getPackageInfo(this.getClass().getPackage().getNam e(), 0).versionName +'\n';
                      } catch (PackageManager.NameNotFoundException e) {
                      e.printStackTrace();
                      rcVersion = e.getLocalizedMessage() + '\n';
                      }

                      String rcLib = "RC Library: " + Version.getLibraryVersion() +'\n';

                      StringBuilder deviceLogBuilder = new StringBuilder("Devices: \n");
                      deviceLogBuilder.append((new DeviceMap<>(hardwareMap.dcMotorController)).detail s());
                      deviceLogBuilder.append((new DeviceMap<>(hardwareMap.dcMotor)).details());
                      deviceLogBuilder.append((new DeviceMap<>(hardwareMap.servoController)).details( ));
                      deviceLogBuilder.append((new DeviceMap<>(hardwareMap.servo)).details());
                      deviceLogBuilder.append((new DeviceMap<>(hardwareMap.legacyModule)).details());
                      deviceLogBuilder.append((new DeviceMap<>(hardwareMap.deviceInterfaceModule)).de tails());
                      deviceLogBuilder.append((new DeviceMap<>(hardwareMap.analogInput)).details());
                      deviceLogBuilder.append((new DeviceMap<>(hardwareMap.digitalChannel)).details() );
                      deviceLogBuilder.append((new DeviceMap<>(hardwareMap.pwmOutput)).details());
                      deviceLogBuilder.append((new DeviceMap<>(hardwareMap.i2cDevice)).details());
                      deviceLogBuilder.append((new DeviceMap<>(hardwareMap.analogOutput)).details());
                      deviceLogBuilder.append((new DeviceMap<>(hardwareMap.led)).details());

                      StringBuilder result = new StringBuilder(this.getClass().getSimpleName() + '\n');
                      result.append(board).append(brand).append(model).a ppend(serial).append(version)
                      .append(rcVersion).append(rcLib).append(deviceLogB uilder).append(log).trimToSize();

                      String msg = result.toString();
                      Log.i(this.getClass().getSimpleName(), msg);
                      RobotLog.setGlobalErrorMsg(msg.substring(0, msg.length() < 256 ? msg.length() : 255));

                      final RelativeLayout layout = (RelativeLayout)
                      ((Activity) hardwareMap.appContext).findViewById(R.id.Relative Layout);
                      final String message = msg;
                      layout.post(new Runnable() {
                      @Override
                      public void run() {
                      TextView child = new TextView(hardwareMap.appContext);
                      child.setText(message);
                      RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
                      ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
                      layoutParams.addRule(RelativeLayout.BELOW, R.id.textErrorMessage);
                      ScrollView scrollView = new ScrollView(hardwareMap.appContext);
                      scrollView.addView(child);
                      layout.addView(scrollView, layoutParams);
                      }
                      });
                      }

                      @Override
                      public void loop() {

                      }


                      }


                      class DeviceMap<K, T> extends HashMap<String, T> {
                      public DeviceMap(HardwareMap.DeviceMapping<T> deviceMapping) {
                      super(deviceMapping.size());
                      buildFromDeviceMapping(deviceMapping);
                      }

                      public DeviceMap<K, T> buildFromDeviceMapping(HardwareMap.DeviceMapping<T > deviceMapping) {
                      Set<Entry<String, T>> entries = deviceMapping.entrySet();
                      for (Entry<String, T> device : entries) {
                      super.put(device.getKey(), device.getValue());
                      }
                      return this;
                      }

                      public String details() {
                      StringBuilder stringBuilder = new StringBuilder();

                      for (Map.Entry<String, T> entry : entrySet()) {
                      T value = entry.getValue();
                      stringBuilder.append(value.getClass().getSimpleNam e()).append(" ")
                      .append(entry.getKey()).append(" ")
                      .append(value.toString()).append('\n');
                      }
                      return stringBuilder.toString();
                      }
                      }

                      Comment


                      • #12
                        Unforunately, I can't update my last post to properly wrap the code in code braces, so here it is in code braces:
                        Code:
                        public class Diag extends OpMode {
                            private static String TAG = "DIAGNOSITCS::";
                            @Override
                            public void init() {        
                                String log = "Log:\n";
                                try {
                                    Process logcat = Runtime.getRuntime().exec("logcat -d");
                                    Thread.sleep(1000);
                                    BufferedReader reader = new BufferedReader(new InputStreamReader(logcat.getInputStream()));
                        
                                    CharBuffer chars = CharBuffer.allocate(8192);
                                    reader.read(chars);
                                    log += chars.toString();
                                } catch (IOException e) {
                                    Log.e(TAG, "Cannot start logcat monitor", e);
                                    log += e.getLocalizedMessage();
                                } catch (InterruptedException e) {
                                    return;
                                }
                        
                                if (log.equals("Log:\n")) {
                                    FileInputStream logcatFile = null;
                                    try {
                                        File file = new File("/sdcard/com.qualcomm.ftcrobotcontroller.logcat");
                                        logcatFile = new FileInputStream(file);
                                        InputStreamReader reader = new InputStreamReader(logcatFile);
                        
                                        char[] chars = new char[(int) file.length()];
                                        reader.read(chars);
                                        log += new String(chars);
                                    } catch (IOException e) {
                                        Log.e(TAG, e.getLocalizedMessage(), e);
                                    }
                                }
                                    String board = "Board: " + Build.BOARD +'\n';
                                String brand = "Brand: " + Build.BRAND +'\n';
                                String model = "Model No: " + Build.MODEL +'\n';
                                String serial = "RC Serial: " + Build.SERIAL +'\n';
                                String version = "Android Version: " + Build.VERSION.RELEASE +'\n';
                        
                                String rcVersion;
                                try {
                                    rcVersion = "RC Version: " + hardwareMap.appContext.getPackageManager().
                                        getPackageInfo(this.getClass().getPackage().getName(), 0).versionName +'\n';
                                } catch (PackageManager.NameNotFoundException e) {
                                    e.printStackTrace();
                                    rcVersion = e.getLocalizedMessage() + '\n';
                                }
                                
                                String rcLib = "RC Library: " + Version.getLibraryVersion() +'\n';
                        
                                StringBuilder deviceLogBuilder = new StringBuilder("Devices: \n");
                                deviceLogBuilder.append((new DeviceMap<>(hardwareMap.dcMotorController)).details());
                                deviceLogBuilder.append((new DeviceMap<>(hardwareMap.dcMotor)).details());
                                deviceLogBuilder.append((new DeviceMap<>(hardwareMap.servoController)).details());
                                deviceLogBuilder.append((new DeviceMap<>(hardwareMap.servo)).details());
                                deviceLogBuilder.append((new DeviceMap<>(hardwareMap.legacyModule)).details());
                                deviceLogBuilder.append((new DeviceMap<>(hardwareMap.deviceInterfaceModule)).details());
                                deviceLogBuilder.append((new DeviceMap<>(hardwareMap.analogInput)).details());
                                deviceLogBuilder.append((new DeviceMap<>(hardwareMap.digitalChannel)).details());
                                deviceLogBuilder.append((new DeviceMap<>(hardwareMap.pwmOutput)).details());
                                deviceLogBuilder.append((new DeviceMap<>(hardwareMap.i2cDevice)).details());
                                deviceLogBuilder.append((new DeviceMap<>(hardwareMap.analogOutput)).details());
                                deviceLogBuilder.append((new DeviceMap<>(hardwareMap.led)).details());
                        
                                StringBuilder result = new StringBuilder(this.getClass().getSimpleName() + '\n');
                                result.append(board).append(brand).append(model).append(serial).append(version)
                                        .append(rcVersion).append(rcLib).append(deviceLogBuilder).append(log).trimToSize();
                        
                                String msg = result.toString();
                                Log.i(this.getClass().getSimpleName(), msg);
                                RobotLog.setGlobalErrorMsg(msg.substring(0, msg.length() < 256 ? msg.length() : 255));
                        
                                final RelativeLayout layout = (RelativeLayout)
                                        ((Activity) hardwareMap.appContext).findViewById(R.id.RelativeLayout);
                                final String message = msg;
                                layout.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        TextView child = new TextView(hardwareMap.appContext);
                                        child.setText(message);
                                        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
                                                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
                                        layoutParams.addRule(RelativeLayout.BELOW, R.id.textErrorMessage);
                                        ScrollView scrollView = new ScrollView(hardwareMap.appContext);
                                        scrollView.addView(child);
                                        layout.addView(scrollView, layoutParams);
                                    }
                                });
                            }
                        
                            @Override
                            public void loop() {
                        
                            }
                            
                            
                        }
                        
                        
                        class DeviceMap<K, T> extends HashMap<String, T> {
                            public DeviceMap(HardwareMap.DeviceMapping<T> deviceMapping) {
                                super(deviceMapping.size());
                                buildFromDeviceMapping(deviceMapping);
                            }
                        
                            public DeviceMap<K, T> buildFromDeviceMapping(HardwareMap.DeviceMapping<T> deviceMapping) {
                                Set<Entry<String, T>> entries = deviceMapping.entrySet();
                                for (Entry<String, T> device : entries) {
                                    super.put(device.getKey(), device.getValue());
                                }
                                return this;
                            }
                        
                            public String details() {
                                StringBuilder stringBuilder = new StringBuilder();
                        
                                for (Map.Entry<String, T> entry : entrySet()) {
                                    T value = entry.getValue();
                                    stringBuilder.append(value.getClass().getSimpleName()).append(" ")
                                            .append(entry.getKey()).append(" ")
                                            .append(value.toString()).append('\n');
                                }
                                return  stringBuilder.toString();
                            }
                        }

                        Comment


                        • #13
                          dmssargent,
                          Thanks!
                          Martin Haeberli
                          Mentor, Team 7593 TigerBots

                          Comment


                          • #14
                            Originally posted by mhaeberli View Post
                            dlevy,
                            Excuse me for being dense, but I couldn't seem to find ViewLogsActivity.java in the standard ftc_app release source code base.
                            Please advise in more detail as to how to make the change you suggest.
                            Thanks,
                            Martin Haeberli
                            Mentor, Team 7593 TigerBots
                            ----
                            Excuse me for being vague. The comment was meant for FTC as a suggested enhancement to their "view logs" function. Considering the amount of folks that need to send logs to FTC for evaluation, I think its an appropriate enhancement that they should make - rather than expecting everyone to augment their SDK to capture log data from the phone.

                            Comment


                            • #15
                              Originally posted by dmssargent View Post
                              You can't change the file, due to it being in a closed source library.
                              I wrote a quick OpMode to show basic diagnostics info:...
                              In the current RC app, hit the top right menu (the three vertical dots). Then select "View Logs".
                              That's the existing FTC feature that takes the locat file and displays it on the screen.

                              My suggestion was that FTC change this to offer one the ability to email that same log file as an attachment.

                              hence:
                              Code:
                              Intent intent = new Intent(Intent.ACTION_SEND);
                              intent.putExtra(Intent.EXTRA_SUBJECT, "Error Log reported");
                              intent.putExtra(Intent.EXTRA_EMAIL, new String[]{ <email address>});
                              intent.putExtra(Intent.EXTRA_TEXT, "Please see attached file);
                              intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(<path to logfile>)));
                              intent.setType("text/plain");

                              Perhaps FTC can also improve their existing "View Logs" feature by incorporating much of what you supplied in OpMode example.

                              -David

                              Comment

                              Working...
                              X