whylabs/whylogs-python

View on GitHub
java/core/src/main/java/com/whylogs/core/views/ColumnProfileView.java

Summary

Maintainability
A
3 hrs
Test Coverage
package com.whylogs.core.views;

import com.whylogs.core.SummaryConfig;
import com.whylogs.core.errors.UnsupportedError;
import com.whylogs.core.metrics.Metric;
import com.whylogs.core.metrics.components.MetricComponent;
import java.util.*;
import lombok.Getter;

@Getter
public class ColumnProfileView {
  private HashMap<String, Metric<?>> metrics;
  private int successes = 0;
  private int failures = 0;

  public ColumnProfileView(HashMap<String, Metric<?>> metrics) {
    this.metrics = metrics;
  }

  public ColumnProfileView(HashMap<String, Metric<?>> metrics, int successes, int failures) {
    this.metrics = new HashMap<>();
    if (metrics != null) {
      this.metrics.putAll(metrics);
    }
    this.successes = successes;
    this.failures = failures;
  }

  public ColumnProfileView merge(ColumnProfileView otherView) {
    if (otherView == null) {
      // TODO: log warning that otehrwas null and this returns original
      return this;
    }

    HashSet<String> allMetricNames = new HashSet<>();
    allMetricNames.addAll(this.metrics.keySet());
    allMetricNames.addAll(otherView.metrics.keySet());

    HashMap<String, Metric<?>> mergedMetrics = new HashMap<>();
    for (String metricName : allMetricNames) {
      Metric<?> thisMetric = this.metrics.get(metricName);
      Metric<?> otherMetric = otherView.metrics.get(metricName);

      Metric<?> result = thisMetric;

      if (thisMetric != null && otherMetric != null) {
        result = thisMetric.merge(otherMetric);
      } else if (otherMetric != null) {
        result = otherMetric;
      }

      mergedMetrics.put(metricName, result);
    }

    return new ColumnProfileView(
        mergedMetrics, this.successes + otherView.successes, this.failures + otherView.failures);
  }

  public Optional<Metric<?>> getMetric(String metricName) {
    return Optional.ofNullable(this.metrics.get(metricName));
  }

  public static ColumnProfileView zero() {
    return new ColumnProfileView(new HashMap<>());
  }

  // TODO: metric needs a getComponentPath
  public List<String> getMetricComponentPaths() {
    ArrayList<String> paths = new ArrayList<>();
    for (String metricName : this.getMetricNames()) {
      Optional<Metric<?>> metric = this.getMetric(metricName);
      if (metric.isPresent()) {
        for (String componentName : metric.get().getComponents().keySet()) {
          paths.add(metricName + "/" + componentName);
        }
      }
    }
    return Collections.unmodifiableList(paths);
  }

  public ArrayList<String> getMetricNames() {
    return new ArrayList<>(this.getMetrics().keySet());
  }

  public HashMap<String, Object> toSummaryDict(
      Optional<String> columnMetric, Optional<SummaryConfig> config) throws UnsupportedError {
    SummaryConfig summaryConfig = config.orElse(new SummaryConfig());
    HashMap<String, Object> summary = new HashMap<>();

    if (columnMetric.isPresent()) {
      summary.putAll(getMetricSummaryHelper(summaryConfig, this.getMetric(columnMetric.get())));
    } else {
      for (String metricName : this.getMetricNames()) {
        summary.putAll(getMetricSummaryHelper(summaryConfig, this.getMetric(metricName)));
      }
    }

    // TODO: there was a logger for when a summary couldn't be implmented for a metric

    if (columnMetric.isPresent() && columnMetric.get().length() == 0) {
      throw new UnsupportedError(
          "No metric available for requested column metric: " + columnMetric.get());
    }
    return summary;
  }

  private Map<String, Object> getMetricSummaryHelper(
      SummaryConfig summaryConfig, Optional<Metric<?>> maybeMetric) {
    HashMap<String, Object> result = new HashMap<>();
    Metric<?> metric;
    if (maybeMetric.isPresent()) {
      metric = maybeMetric.get();
      HashMap<String, Object> metricSummary = metric.toSummaryDict(summaryConfig);
      for (String componentName : metricSummary.keySet()) {
        String fullName = metric.getNamespace() + "/" + componentName;
        result.put(fullName, metricSummary.get(componentName));
      }
    }
    return Collections.unmodifiableMap(result);
  }

  public Map<String, MetricComponent> getComponents() {
    HashMap<String, MetricComponent> result = new HashMap<>();
    for (String metricName : this.getMetricNames()) {
      Optional<Metric<?>> metric = this.getMetric(metricName);
      metric.ifPresent(value -> result.putAll(value.getComponents()));
    }
    return Collections.unmodifiableMap(result);
  }
}