All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.datadoghq.trace.integration.URLAsResourceName Maven / Gradle / Ivy

There is a newer version: 0.2.12
Show newest version
package com.datadoghq.trace.integration;

import com.datadoghq.trace.DDSpanContext;
import com.datadoghq.trace.DDTags;
import com.datadoghq.trace.resolver.DDTracerFactory;
import com.datadoghq.trace.resolver.FactoryUtils;
import com.datadoghq.trace.resolver.TracerConfig;
import io.opentracing.tag.Tags;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/** Decorator for servlet contrib */
public class URLAsResourceName extends AbstractDecorator {

  public static final Config.Rule RULE_QPARAM = new Config.Rule("\\?.*$", "");
  public static final Config.Rule RULE_DIGIT = new Config.Rule("\\d+", "?");
  private List patterns = new ArrayList<>();

  public URLAsResourceName() {
    this(DDTracerFactory.CONFIG_PATH);
  }

  public URLAsResourceName(final String configPath) {

    super();
    this.setMatchingTag(Tags.HTTP_URL.getKey());
    this.setSetTag(DDTags.RESOURCE_NAME);

    try {
      final Config config = FactoryUtils.loadConfigFromResource(configPath, Config.class);
      for (final Config.Rule pattern : config.urlResourcePatterns) {
        patterns.add(pattern);
      }
    } catch (final Throwable ex) {
      // do nothing
    } finally {
      patterns.add(RULE_QPARAM);
      patterns.add(RULE_DIGIT);
    }
  }

  @Override
  public boolean afterSetTag(final DDSpanContext context, final String tag, final Object value) {
    try {
      final String statusCode = String.valueOf(context.getTags().get(Tags.HTTP_STATUS.getKey()));
      // do nothing if the status code is already set and equals to 404.
      // TODO: it assumes that Status404Decorator is active. If it's not, it will lead to unexpected behaviors
      if (statusCode != null && statusCode.equals("404")) {
        return true;
      }

      // Get the path without host:port
      String path = String.valueOf(value);

      try {
        path = new java.net.URL(path).getPath();
      } catch (final MalformedURLException e) {
        // do nothing, use the value instead of the path
      }
      // normalize the path
      path = norm(path);

      // if the verb (GET, POST ...) is present, add it
      final String verb = (String) context.getTags().get(Tags.HTTP_METHOD.getKey());
      if (verb != null && !verb.isEmpty()) {
        path = verb + " " + path;
      }

      context.setResourceName(path);
    } catch (final Throwable e) {
      return false;
    }
    return true;
  }

  // Method to normalise the url string
  String norm(final String origin) {

    String norm = origin;

    // Apply rules
    for (final Config.Rule p : patterns) {
      norm = norm.replaceAll(p.regex, p.replacement);
      // if the rule is final, so do not apply others functions
      if (p.isFinal) {
        break;
      }
    }

    return norm;
  }

  // For tests
  List getPatterns() {
    return patterns;
  }

  // For tests
  void setPatterns(final List patterns) {
    this.patterns = patterns;
  }

  /** Additional properties concerning the UrlAsResourceDecorator in the YAML config */
  public static class Config extends TracerConfig {

    List urlResourcePatterns;

    public List getUrlResourcePatterns() {
      return urlResourcePatterns;
    }

    public void setUrlResourcePatterns(final List urlResourcePatterns) {
      this.urlResourcePatterns = urlResourcePatterns;
    }

    public static class Rule {

      String regex;
      String replacement;
      boolean isFinal = false;

      public Rule() {}

      public Rule(final String regex, final String replacement) {
        this.regex = regex;
        this.replacement = replacement;
      }

      public String getRegex() {
        return regex;
      }

      public void setRegex(final String regex) {
        this.regex = regex;
      }

      public String getReplacement() {
        return replacement;
      }

      public void setReplacement(final String replacement) {
        this.replacement = replacement;
      }

      public boolean isFinal() {
        return isFinal;
      }

      public void setFinal(final boolean isFinal) {
        this.isFinal = isFinal;
      }

      @Override
      public boolean equals(final Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        final Rule rule = (Rule) o;
        return Objects.equals(regex, rule.regex) && Objects.equals(replacement, rule.replacement);
      }

      @Override
      public int hashCode() {
        return Objects.hash(regex, replacement, isFinal);
      }
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy