diff --git a/gcloud-java-logging/src/main/java/com/google/cloud/logging/MetricInfo.java b/gcloud-java-logging/src/main/java/com/google/cloud/logging/MetricInfo.java
new file mode 100644
index 000000000000..e4f1e97cfded
--- /dev/null
+++ b/gcloud-java-logging/src/main/java/com/google/cloud/logging/MetricInfo.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.cloud.logging;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.MoreObjects;
+import com.google.logging.v2.LogMetric;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+/**
+ * Google Cloud Logging metrics describe logs-based metric. The value of the metric is the number of
+ * log entries that match a logs filter (see {@link #filter()}).
+ *
+ * @see Logs-based Metrics
+ *
+ */
+public class MetricInfo implements Serializable {
+
+ private static final long serialVersionUID = 666208243838820325L;
+
+ private final String name;
+ private final String description;
+ private final String filter;
+
+ /**
+ * A builder for {@code MetricInfo} objects.
+ */
+ public abstract static class Builder {
+
+ /**
+ * Sets the name of the metric. Example: {@code severe-errors}. Metric identifiers are
+ * limited to 1000 characters and can include only the following characters: {@code A-Z},
+ * {@code a-z}, {@code 0-9}, and the special characters {@code _-.,+!*',()%/\}. The
+ * forward-slash character ({@code /}) denotes a hierarchy of name pieces, and it cannot be the
+ * first character of the name.
+ */
+ public abstract Builder name(String name);
+
+ /**
+ * Sets an optional description for this metric. Used for documentation purpose.
+ */
+ public abstract Builder description(String description);
+
+ /**
+ * Sets an advanced logs filter. The value of the metric is the number of log entries that match
+ * this filter. Example: {@code logName=projects/my-projectid/logs/syslog AND severity>=ERROR}.
+ *
+ * @see Advanced Log
+ * Filters
+ */
+ public abstract Builder filter(String filter);
+
+ /**
+ * Creates a {@code MetricInfo} object for this builder.
+ */
+ public abstract MetricInfo build();
+ }
+
+ static final class BuilderImpl extends Builder {
+
+ private String name;
+ private String description;
+ private String filter;
+
+ BuilderImpl(String name, String filter) {
+ this.name = name;
+ this.filter = filter;
+ }
+
+ BuilderImpl(MetricInfo metric) {
+ this.name = metric.name;
+ this.description = metric.description;
+ this.filter = metric.filter;
+ }
+
+ @Override
+ public Builder name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ @Override
+ public Builder description(String description) {
+ this.description = description;
+ return this;
+ }
+
+ @Override
+ public Builder filter(String filter) {
+ this.filter = filter;
+ return this;
+ }
+
+ @Override
+ public MetricInfo build() {
+ return new MetricInfo(this);
+ }
+ }
+
+ MetricInfo(BuilderImpl builder) {
+ this.name = checkNotNull(builder.name);
+ this.filter = checkNotNull(builder.filter);
+ this.description = builder.description;
+ }
+
+ /**
+ * Returns the name of the metric. Example: {@code severe-errors}. Metric identifiers are
+ * limited to 1000 characters and can include only the following characters: {@code A-Z},
+ * {@code a-z}, {@code 0-9}, and the special characters {@code _-.,+!*',()%/\}. The
+ * forward-slash character ({@code /}) denotes a hierarchy of name pieces, and it cannot be the
+ * first character of the name.
+ */
+ public String name() {
+ return name;
+ }
+
+ /**
+ * Returns an optional description for this metric. Used for documentation purpose.
+ */
+ public String description() {
+ return description;
+ }
+
+ /**
+ * Returns an advanced logs filter. The value of the metric is the number of log entries that
+ * match this filter. Example:
+ * {@code logName=projects/my-projectid/logs/syslog AND severity>=ERROR}.
+ *
+ * @see Advanced Log
+ * Filters
+ */
+ public String filter() {
+ return filter;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("name", name)
+ .add("description", description)
+ .add("filter", filter)
+ .toString();
+ }
+
+ final boolean baseEquals(MetricInfo metricInfo) {
+ return Objects.equals(name, metricInfo.name)
+ && Objects.equals(description, metricInfo.description)
+ && Objects.equals(filter, metricInfo.filter);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj == null || !(obj.getClass().equals(MetricInfo.class))) {
+ return false;
+ }
+ return baseEquals((MetricInfo) obj);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, description, filter);
+ }
+
+ /**
+ * Returns a builder for this {@code MetricInfo} object.
+ */
+ public Builder toBuilder() {
+ return new BuilderImpl(this);
+ }
+
+ /**
+ * Returns a builder for {@code MetricInfo} objects given the name of the metric and its filter.
+ */
+ public static Builder builder(String name, String filter) {
+ return new BuilderImpl(name, filter);
+ }
+
+ /**
+ * Creates a {@code MetricInfo} object given the name of the metric and its filter.
+ */
+ public static MetricInfo of(String name, String filter) {
+ return new BuilderImpl(name, filter).build();
+ }
+
+ LogMetric toPb() {
+ LogMetric.Builder builder = LogMetric.newBuilder()
+ .setName(name)
+ .setFilter(filter);
+ if (description != null) {
+ builder.setDescription(description);
+ }
+ return builder.build();
+ }
+
+ static MetricInfo fromPb(LogMetric metricPb) {
+ Builder builder = builder(metricPb.getName(), metricPb.getFilter());
+ if (!metricPb.getDescription().equals("")) {
+ builder.description(metricPb.getDescription());
+ }
+ return builder.build();
+ }
+}
diff --git a/gcloud-java-logging/src/test/java/com/google/cloud/logging/MetricInfoTest.java b/gcloud-java-logging/src/test/java/com/google/cloud/logging/MetricInfoTest.java
new file mode 100644
index 000000000000..5b4be469cbbb
--- /dev/null
+++ b/gcloud-java-logging/src/test/java/com/google/cloud/logging/MetricInfoTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.cloud.logging;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+
+public class MetricInfoTest {
+
+ private static final String NAME = "name";
+ private static final String FILTER = "logName=projects/my-projectid/logs/syslog";
+ private static final String DESCRIPTION = "description";
+ private static final String NEW_NAME = "newName";
+ private static final String NEW_FILTER = "logName=projects/my-projectid/logs/newSyslog";
+ private static final String NEW_DESCRIPTION = "newDescription";
+ private static final MetricInfo METRIC_INFO = MetricInfo.builder(NAME, FILTER)
+ .description(DESCRIPTION)
+ .build();
+
+ @Test
+ public void testOf() {
+ MetricInfo metricInfo = MetricInfo.of(NAME, FILTER);
+ assertEquals(NAME, metricInfo.name());
+ assertEquals(FILTER, metricInfo.filter());
+ assertNull(metricInfo.description());
+ }
+
+ @Test
+ public void testBuilder() {
+ assertEquals(NAME, METRIC_INFO.name());
+ assertEquals(FILTER, METRIC_INFO.filter());
+ assertEquals(DESCRIPTION, METRIC_INFO.description());
+ }
+
+ @Test
+ public void testToBuilder() {
+ compareMetricInfo(METRIC_INFO, METRIC_INFO.toBuilder().build());
+ MetricInfo metricInfo = METRIC_INFO.toBuilder()
+ .name(NEW_NAME)
+ .description(NEW_DESCRIPTION)
+ .filter(NEW_FILTER)
+ .build();
+ assertEquals(NEW_NAME, metricInfo.name());
+ assertEquals(NEW_FILTER, metricInfo.filter());
+ assertEquals(NEW_DESCRIPTION, metricInfo.description());
+ metricInfo = metricInfo.toBuilder()
+ .name(NAME)
+ .description(DESCRIPTION)
+ .filter(FILTER)
+ .build();
+ compareMetricInfo(METRIC_INFO, metricInfo);
+ }
+
+ @Test
+ public void testToAndFromPb() {
+ compareMetricInfo(METRIC_INFO, MetricInfo.fromPb(METRIC_INFO.toPb()));
+ MetricInfo metricInfo = MetricInfo.of(NAME, FILTER);
+ compareMetricInfo(metricInfo, MetricInfo.fromPb(metricInfo.toPb()));
+ }
+
+ private void compareMetricInfo(MetricInfo expected, MetricInfo value) {
+ assertEquals(expected, value);
+ assertEquals(expected.name(), value.name());
+ assertEquals(expected.description(), value.description());
+ assertEquals(expected.filter(), value.filter());
+ assertEquals(expected.hashCode(), value.hashCode());
+ assertEquals(expected.toString(), value.toString());
+ }
+}