code: @Override
      public void visitVariables(VariableVisitor visitor) {
          // build a collection of live variables in a synchronized block
          final List<Variable> variablesCopy;
          synchronized (variables) {
              variablesCopy = Lists.newArrayListWithExpectedSize(variables.size());
              final Iterator<Variable> iterator = variables.values().iterator();
              while (iterator.hasNext()) {
                  final Variable v = iterator.next();
                  if (v.isLive()) {
                      variablesCopy.add(v);
                  } else {
                      // remove-on-read of variables that are no longer live
                      // javadoc says this removes from the mapping from the map
                      iterator.remove();
                  }
              }
          }
  
          for (Variable v : variablesCopy) {
              if (v.isExpandable()) {
                  Map<?, ?> map = v.expand();
                  try {
                      for (final Map.Entry entry : map.entrySet()) {
                          visitor.visit(new EntryVariable(entry, v, namespace));
                      }
                  } catch (ConcurrentModificationException e) {
                      log.warn("Failed to iterate map entry set for variable " + v.getName(), e);
                      Map.Entry<String, String> errorEntry = new AbstractMap.SimpleEntry<String, String>("error", e.getMessage());
                      visitor.visit(new EntryVariable(errorEntry, v, namespace));
                  }
              } else {
                  visitor.visit(v);
              }
          }
          if (variablesCopy.size() > 0 && startTime != null) {
              visitor.visit(startTime);
          }
      }
docs: Visit all the values exported by this exporter.
  @param visitor visitor to receive visit callbacks