From 1fa3a6e286336a861f83d9b59f28f309fc846d70 Mon Sep 17 00:00:00 2001 From: minherz Date: Fri, 22 Oct 2021 09:52:47 +0300 Subject: [PATCH] feat: add population of the SourceLocation from context (#721) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add population of the SourceLocation from context * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md Co-authored-by: Owl Bot --- .../google/cloud/logging/SourceLocation.java | 28 +++++++++++++++++++ .../cloud/logging/SourceLocationTest.java | 21 ++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/SourceLocation.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/SourceLocation.java index 738dbcc7a..df9126687 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/SourceLocation.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/SourceLocation.java @@ -16,6 +16,8 @@ package com.google.cloud.logging; +import static com.google.common.base.Preconditions.checkElementIndex; + import com.google.common.base.MoreObjects; import com.google.logging.v2.LogEntrySourceLocation; import java.io.Serializable; @@ -154,4 +156,30 @@ static SourceLocation fromPb(LogEntrySourceLocation sourceLocationPb) { .setFunction(sourceLocationPb.getFunction()) .build(); } + + /** + * Creates instance of {@link SourceLocation} based on stack trace information. Caller should + * provide the level in the stack where the information can be located. The stack trace level + * should be {@code 0} to display information for the caller of the method. + * + * @param level Zero-based non-negative integer defining the level in the stack trace where {@code + * 0} is topmost element. + * @return a new instance of {@link SourceLocation} populated with file name, method and line + * number information. + * @throws IndexOutOfBoundsException if the provided {@link level} is negative or greater than the + * current call stack. + */ + static SourceLocation fromCurrentContext(int level) { + StackTraceElement[] stackTrace = (new Exception()).getStackTrace(); + Builder builder = newBuilder(); + // need to take info from 1 level down the stack to compensate the call to this + // method + int indexPlus = checkElementIndex(level, stackTrace.length - 1) + 1; + StackTraceElement ste = stackTrace[indexPlus]; + return builder + .setFile(ste.getFileName()) + .setLine(Long.valueOf(ste.getLineNumber())) + .setFunction(ste.getMethodName()) + .build(); + } } diff --git a/google-cloud-logging/src/test/java/com/google/cloud/logging/SourceLocationTest.java b/google-cloud-logging/src/test/java/com/google/cloud/logging/SourceLocationTest.java index 6a955584e..e9feb2f9f 100644 --- a/google-cloud-logging/src/test/java/com/google/cloud/logging/SourceLocationTest.java +++ b/google-cloud-logging/src/test/java/com/google/cloud/logging/SourceLocationTest.java @@ -58,6 +58,27 @@ public void testToAndFromPb() { compareSourceLocation(SOURCE_LOCATION, SourceLocation.fromPb(SOURCE_LOCATION.toPb())); } + @Test + public void testFromCurrentContext() { + StackTraceElement expectedData = (new Exception()).getStackTrace()[0]; + SourceLocation data = SourceLocation.fromCurrentContext(0); + assertEquals(expectedData.getFileName(), data.getFile()); + assertEquals(expectedData.getMethodName(), data.getFunction()); + // mind the assertion is vs (expectedData.lineNumber + 1). it is because the source location + // info of the expectedData is one line above the source location of the tested data. + assertEquals(Long.valueOf(expectedData.getLineNumber() + 1), data.getLine()); + } + + @Test(expected = IndexOutOfBoundsException.class) + public void testFromCurrentContextWithNegativeLevel() { + SourceLocation.fromCurrentContext(-1); + } + + @Test(expected = IndexOutOfBoundsException.class) + public void testFromCurrentContextWithVeryLargeLevel() { + SourceLocation.fromCurrentContext(10000); + } + private void compareSourceLocation(SourceLocation expected, SourceLocation value) { assertEquals(expected, value); assertEquals(expected.getFile(), value.getFile());