Skip to content

Commit

Permalink
#4 Custom type for Class type;
Browse files Browse the repository at this point in the history
Also adding CLASS_NAME() function
  • Loading branch information
gunnarmorling committed Dec 26, 2021
1 parent 0d9f6ca commit 2b19a39
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 4 deletions.
34 changes: 34 additions & 0 deletions src/main/java/org/moditect/jfranalytics/GetClassNameFunction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright 2021 The original authors
*
* 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 org.moditect.jfranalytics;

import org.apache.calcite.schema.ScalarFunction;
import org.apache.calcite.schema.impl.ScalarFunctionImpl;

import jdk.jfr.consumer.RecordedClass;

public class GetClassNameFunction {

public static final ScalarFunction INSTANCE = ScalarFunctionImpl.create(GetClassNameFunction.class, "eval");

public String eval(Object recordedClass) {
if (!(recordedClass instanceof RecordedClass)) {
System.out.println(recordedClass);
throw new RuntimeException("BOOM");
}
return ((RecordedClass) recordedClass).getName();
}
}
18 changes: 14 additions & 4 deletions src/main/java/org/moditect/jfranalytics/JfrSchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import jdk.jfr.Timespan;
import jdk.jfr.ValueDescriptor;
import jdk.jfr.consumer.EventStream;
import jdk.jfr.consumer.RecordedClass;

public class JfrSchema implements Schema {

Expand Down Expand Up @@ -75,7 +76,12 @@ private static Map<String, JfrScannableTable> getTableTypes(Path jfrFile) {
continue;
}

// if (type.getSqlTypeName().toString().equals("ROW")) {
// builder.add(field.getName(), type).nullable(true);
// }

builder.add(field.getName(), type.getSqlTypeName()).nullable(true);

converters.add(getConverter(field, type));
}

Expand Down Expand Up @@ -107,7 +113,7 @@ private static RelDataType getRelDataType(EventType eventType, ValueDescriptor f
}
break;
case "java.lang.Class":
type = typeFactory.createJavaType(String.class);
type = typeFactory.createJavaType(RecordedClass.class);
break;
case "java.lang.String":
type = typeFactory.createJavaType(String.class);
Expand All @@ -119,7 +125,7 @@ private static RelDataType getRelDataType(EventType eventType, ValueDescriptor f
type = typeFactory.createJavaType(String.class);
break;
default:
LOGGER.log(Level.WARNING, "Unknown attribute type: {0}; event type {1}", field.getTypeName(), eventType.getName());
LOGGER.log(Level.WARNING, "Unknown type of attribute {0}::{1}: {2}", eventType.getName(), field.getName(), field.getTypeName());
type = null;
}
return type;
Expand Down Expand Up @@ -148,7 +154,7 @@ else if (type != null && type.getSqlTypeName() == SqlTypeName.BIGINT) {
}
else {
if (field.getTypeName().equals("java.lang.Class")) {
return event -> event.getClass(field.getName()).getName();
return event -> event.getClass(field.getName());
}
else {
return event -> event.getValue(field.getName());
Expand Down Expand Up @@ -179,12 +185,16 @@ public Set<String> getTypeNames() {

@Override
public Collection<Function> getFunctions(String name) {
if (name.equals("CLASS_NAME")) {
return Collections.singleton(GetClassNameFunction.INSTANCE);
}

return Collections.emptySet();
}

@Override
public Set<String> getFunctionNames() {
return Collections.emptySet();
return Set.of("CLASS_NAME");
}

@Override
Expand Down
56 changes: 56 additions & 0 deletions src/test/java/org/moditect/jfranalytics/JfrSchemaFactoryTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,62 @@ public void canRunSimpleSelectFromGarbageCollection() throws Exception {
}
}

@Test
public void canRunSimpleSelectFromClassLoad() throws Exception {
try (Connection connection = DriverManager.getConnection("jdbc:calcite:", getConnectionProperties("class-loading.jfr"))) {
PreparedStatement statement = connection.prepareStatement("""
SELECT "startTime", "loadedClass"
FROM "jfr"."jdk.ClassLoad"
ORDER by "startTime"
LIMIT 1
""");

try (ResultSet rs = statement.executeQuery()) {
assertThat(rs.next()).isTrue();

assertThat(rs.getTimestamp(1)).isEqualTo(Timestamp.from(ZonedDateTime.parse("2021-12-26T17:32:45.428000000+01:00").toInstant()));
assertThat(rs.getString(2)).isEqualTo("""
{
classLoader = null
name = "java/lang/Throwable"
package = {
name = "java/lang"
module = {
name = "java.base"
version = "17"
location = "jrt:/java.base"
classLoader = null
}
exported = true
}
modifiers = 33
hidden = false
}
""");

assertThat(rs.next()).isFalse();
}
}
}

@Test
public void canUseGetClassNameFunction() throws Exception {
try (Connection connection = DriverManager.getConnection("jdbc:calcite:", getConnectionProperties("class-loading.jfr"))) {
PreparedStatement statement = connection.prepareStatement("""
SELECT CLASS_NAME("loadedClass") as className
FROM "jfr"."jdk.ClassLoad"
ORDER by "startTime"
LIMIT 1
""");

try (ResultSet rs = statement.executeQuery()) {
assertThat(rs.next()).isTrue();
assertThat(rs.getString(1)).isEqualTo("java.lang.Throwable");
assertThat(rs.next()).isFalse();
}
}
}

@Test
public void canRunAggregation() throws Exception {
try (Connection connection = DriverManager.getConnection("jdbc:calcite:", getConnectionProperties("basic.jfr"))) {
Expand Down
Binary file added src/test/resources/class-loading.jfr
Binary file not shown.

0 comments on commit 2b19a39

Please sign in to comment.