public static boolean matches(MetricsFilter filter, MetricKey key) {
    if (filter == null) {
      return true;
    }

    @Nullable String stepName = key.stepName();
    if (stepName == null) {
      if (!filter.steps().isEmpty()) {
        // The filter specifies steps, but the metric is not associated with a step.
        return false;
      }
    } else if (!matchesScope(stepName, filter.steps())) {
      // The filter specifies steps that differ from the metric's step
      return false;
    }

    // The filter's steps match the metric's step.
    return matchesName(key.metricName(), filter.names());
  }
@Test
  public void testMatchStringNamespaceFilters() {
    // MetricsFilter with a String-namespace + name filter. Without step filter.
    // Successful match.
    assertTrue(
        MetricFiltering.matches(
            MetricsFilter.builder()
                .addNameFilter(MetricNameFilter.named("myNamespace", "myMetricName"))
                .build(),
            MetricKey.create("anyStep", MetricName.named("myNamespace", "myMetricName"))));

    // Unsuccessful match.
    assertFalse(
        MetricFiltering.matches(
            MetricsFilter.builder()
                .addNameFilter(MetricNameFilter.named("myOtherNamespace", "myMetricName"))
                .build(),
            MetricKey.create("anyStep", MetricName.named("myNamespace", "myMetricname"))));
  }