class BaseHandler implements Handler<T> {

  public void init(Context ctx) throws HandlerException {
    /*
     * Function alias is the last part of the Function ARN
     */
    String alias = null;
    String[] tokens = ctx.getInvokedFunctionArn().split(":");
    if (tokens.length == 7) {
      alias = "$LATEST";
    } else if (tokens.length == 8) {
      alias = tokens[7];
    }
    BenderLayout.ALIAS = alias;
    BenderLayout.VERSION = ctx.getFunctionVersion();

    /*
     * Create a new monitor and then get a static copy of it
     */
    monitor = Monitor.getInstance();
    monitor.addTag("functionName", ctx.getFunctionName());
    monitor.addTag("functionVersion", alias);

    String configFile;

    /*
     * TODO: Replace this to always use env vars. Code was written prior to lambda env vars
     * existing.
     */
    if (System.getenv("BENDER_CONFIG") != null) {
      configFile = System.getenv("BENDER_CONFIG");
    } else if (CONFIG_FILE == null) {
      configFile = "/config/" + alias;
    } else {
      configFile = CONFIG_FILE;
    }

    logger.info(String.format("Bender Initializing (config: %s)", configFile));

    try {
      if (configFile.startsWith("s3://")) {
        config = BenderConfig.load(s3ClientFactory, new AmazonS3URI(configFile));
      } else if (configFile.startsWith("file://")) {
        File file = new File(configFile.replaceFirst("file://", ""));
        String string = FileUtils.readFileToString(file);
        config = BenderConfig.load(configFile, string);
      } else {
        config = BenderConfig.load(configFile);
      }
    } catch (ConfigurationException | IOException e) {
      throw new HandlerException("Error loading configuration: " + e.getMessage(), e);
    }

    HandlerResources handlerResources;
    try {
      handlerResources = new HandlerResources(config);
    } catch (ClassNotFoundException e) {
      throw new HandlerException("Unable to load resource: " + e.getMessage(), e);
    }

    /*
     * Add user tags
     */
    monitor.addTags(config.getHandlerConfig().getMetricTags());

    /*
     * Add Lambda function tags. These will override duplicate user tags.
     */
    if (config.getHandlerConfig().getIncludeFunctionTags()) {
      AWSLambda lambda = this.lambdaClientFactory.newInstance();
      ListTagsResult res =
          lambda.listTags(new ListTagsRequest().withResource(ctx.getInvokedFunctionArn()));

      monitor.addTagsMap(
          /*
           * Filter out tags that come from CloudFormation
           */
          res.getTags().entrySet().stream()
              .filter(map -> !map.getKey().startsWith("aws:cloudformation"))
              .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)));
    }

    /*
     * Register reporters
     */
    monitor.addReporters(handlerResources.getReporters());

    /*
     * Init other things
     */
    wrapper = handlerResources.getWrapperFactory().newInstance();
    ser = handlerResources.getSerializerProcessor();
    setIpcService(new IpcSenderService(handlerResources.getTransportFactory()));
    sources = new ArrayList<Source>(handlerResources.getSources().values());
    queueSize = config.getHandlerConfig().getQueueSize();
    initialized = true;
  }

}