saravanarajan / acra

Automatically exported from code.google.com/p/acra
0 stars 0 forks source link

Allow app to add custom data elements at the time of the crash #59

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
This enhancement suggestion is to provide a hook to allow the app to add 
additional custom data elements at the time of the crash (just before the 
report is sent).

The  motivation is to allow an efficient custom logger to include the last N 
items it has stored in the report.

One implementation, as discussed in a group email thread, is below:

There is one thing I don't like about this exact implementation - restrictions 
on the annotation prevented me from maintaining compile-time type safety on the 
crash time data provider class. Note also the use of a TreeMap - this returns 
the tags sorted. You might consider doing that for the other custom data also.

1) Add an annotation to ReportsCrashes that, if present, has the a reference to 
a class which implements an interface with one method which returns a list of 
key/string pairs when called:

            /**
           * Crash time data provider
           *
           * @return
           */

          Class<?> crashTimeProvider() default Object.class;

2) In ErrorReporter, modified the clause where it handles the  custom data as 
follows:

                if (fieldsList.contains(CUSTOM_DATA)) {
                    String custString = createCustomInfoString();
                    // Handle user-provided crash-time custom data provider, if present
                    Class<?> clazz = ACRA.getConfig().crashTimeProvider();
                    if (  Object.class != clazz ) {
                        try {
                            CrashTimeCustomDataProviderA provider = (CrashTimeCustomDataProviderA) clazz.newInstance();
                            Map<String,String> moreData = provider.getCurCustomData();
                            if ( moreData != null ) {
                                for ( String key : moreData.keySet() ) {
                                    custString += key+"="+moreData.get(key)+"\n";
                                }
                            }
                        } catch ( Throwable t ) {
                            custString = custString + "\n CrashTimeCustomDataProvider_Exc:"+t;
                        }
                        mCrashProperties.put(CUSTOM_DATA, custString);
                    }
                }

3) Added an abstract class for the crash-time getter:

    /**
     * Provides data at crash time.
     *
     * Abstract class rather than interface due to limitations on annotions.
     */
    public class CrashTimeCustomDataProviderA {

        public Map<String,String> getCurCustomData() {
            return new TreeMap<String,String>();
        }
    }

...... In my own code, I wrote the following which implements the crash time 
reporter and lets me efficiently keep N most recent trace events (avoidance of 
perfect concurrency consistency is intentional, for performance)

    /**
     * Collects info for the error reporting by ACRA
     */
    public class ACH extends CrashTimeCustomDataProviderA {
      private static final String FORMAT = "%1$ty%1$tm%1$td %1$tH:%1$tM:%1$tS.%1$tL %2$s\n";
      private static final ConcurrentLinkedQueue<MyEntry> events = new ConcurrentLinkedQueue<MyEntry>();

        public static void evt(String msg) {
            MyEntry shell= null;
            if ( events.size() >= CN.ACRS_NUM_EVTS_IN_REPT) {
                shell = events.poll();
            }
            if ( shell == null ) {
                shell = new MyEntry();
            }
            shell.time = System.currentTimeMillis();
            shell.msg = msg;
            events.add(shell);
        }

        @Override
      public TreeMap<String,String> getCurCustomData() {
          // TODO Auto-generated method stub
            TreeMap<String,String> map = new TreeMap<String,String>();
            MyEntry entry;
            StringBuilder sb = new StringBuilder();
            while ( null != (entry = events.poll())) {
                String line = String.format(FORMAT, new Date(entry.time), entry.msg);
                sb.append(line);
            }
          map.put("TVS-TRACE", sb.toString());
          return map;
      }
    }
    class MyEntry {
        long time;
        String msg;
    }

Original issue reported on code.google.com by crotalis...@gmail.com on 27 Jun 2011 at 1:18

GoogleCodeExporter commented 9 years ago
Argh... meant to add this as enhancement request, but don't know how.

Original comment by crotalis...@gmail.com on 27 Jun 2011 at 1:19

GoogleCodeExporter commented 9 years ago

Original comment by william....@gmail.com on 16 Jul 2011 at 7:05

GoogleCodeExporter commented 9 years ago
With ACRA 4.2.3, you can now implement your own ReportSender which can let you 
manipulate data collected by ACRA or implement your own data collection code 
before sending to a custom destination.

Does this allow you to implement what you need ?

Original comment by kevin.gaudin on 26 Nov 2011 at 12:00

GoogleCodeExporter commented 9 years ago

Original comment by kevin.gaudin on 2 Jan 2012 at 9:18