@Override
 public void run() {
   try {
     final Map<String, AScalarDataPoint> m =
         sysMon.getScalarMeasurements(averagingDelayMillis);
     for (String key : m.keySet()) {
       dump("Scalar Measurement: " + key + " = " + m.get(key).getFormattedValue());
     }
   } catch (Exception exc) {
     log.error(exc);
     dump(exc.toString());
   }
 }
  public AHttpJsonOffloadingDataSink(
      final ASysMonApi sysMon,
      String uri,
      String sender,
      String senderInstance,
      int traceQueueSize,
      int scalarQueueSize,
      int numOffloadingThreads,
      int scalarMeasurementFrequencyMillis) {
    this.config = sysMon.getConfig();

    this.uri = URI.create(uri);
    this.sender = sender;
    this.senderInstance = senderInstance;

    this.traceQueue =
        new ASoftlyLimitedQueue<AHierarchicalDataRoot>(
            traceQueueSize, new DiscardedLogger("trace queue overflow - discarding oldest trace"));
    this.scalarQueue =
        new ASoftlyLimitedQueue<AScalarDataPoint>(
            scalarQueueSize,
            new DiscardedLogger("environment queue overflow - discarding oldest data"));

    offloadingThreadPool = Executors.newFixedThreadPool(numOffloadingThreads);
    for (int i = 0; i < numOffloadingThreads; i++) {
      offloadingThreadPool.submit(new OffloadingRunnable());
    }

    scalarMeasurementPool = Executors.newSingleThreadScheduledExecutor();
    scalarMeasurementPool.scheduleAtFixedRate(
        new Runnable() {
          @Override
          public void run() {
            // TODO introduce 'AScalarProvider' interface for callbacks like this
            for (AScalarDataPoint scalar :
                sysMon
                    .getScalarMeasurements()
                    .values()) { // TODO ensure that this ASysMon call will never throw exceptions
              scalarQueue.add(scalar);
            }
          }
        },
        0,
        scalarMeasurementFrequencyMillis,
        TimeUnit.MILLISECONDS);
  }