Skip to content

Commit

Permalink
Expose individual parts of connection details
Browse files Browse the repository at this point in the history
  • Loading branch information
thobe committed Jan 17, 2017
1 parent 58598f0 commit 5ce9180
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 29 deletions.
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@
package org.neo4j.kernel.impl.query; package org.neo4j.kernel.impl.query;


import java.io.Serializable; import java.io.Serializable;
import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;


import static java.util.Objects.requireNonNull;

public abstract class QuerySource public abstract class QuerySource
{ {
public abstract String asConnectionDetails(); public abstract String asConnectionDetails();
Expand All @@ -42,6 +41,21 @@ public String asConnectionDetails()
} }
}; };


public String requestScheme()
{
return null;
}

public String clientAddress()
{
return null;
}

public String requestURI()
{
return null;
}

public static class BoltSession extends QuerySource public static class BoltSession extends QuerySource
{ {
private final String principalName; private final String principalName;
Expand All @@ -64,39 +78,90 @@ public BoltSession(
@Override @Override
public String asConnectionDetails() public String asConnectionDetails()
{ {
return String.format( "bolt-session\tbolt\t%s\t%s\t\tclient%s\tserver%s>", return String.format(
"bolt-session\tbolt\t%s\t%s\t\tclient%s\tserver%s>",
principalName, principalName,
clientName, clientName,
clientAddress, clientAddress,
serverAddress ); serverAddress );
} }

@Override
public String requestScheme()
{
return "bolt";
}

@Override
public String clientAddress()
{
return addressString( clientAddress );
}

@Override
public String requestURI()
{
return addressString( serverAddress );
}

private String addressString( SocketAddress address )
{
if ( address instanceof InetSocketAddress )
{
InetSocketAddress inet = (InetSocketAddress) address;
return String.format( "%s:%s", inet.getHostString(), inet.getPort() );
}
return address.toString();
}
} }


public static class ServerSession extends QuerySource public static class ServerSession extends QuerySource
{ {
private final String scheme; private final String scheme;
private final String remoteAddr; private final InetSocketAddress clientAddress;
private final String requestURI; private final InetSocketAddress serverAddress;
private final String requestPath;

public ServerSession(
String scheme,
@SuppressWarnings( "unused" ) String userAgent, // useful for achieving parity with BoltSession
InetSocketAddress clientAddress,
InetSocketAddress serverAddress,
String requestPath )
{
this.scheme = scheme;
this.clientAddress = clientAddress;
this.serverAddress = serverAddress;
this.requestPath = requestPath;
}

@Override
public String asConnectionDetails()
{
return String.join( "\t", "server-session", scheme, clientAddress.getHostString(), requestPath );
}


public ServerSession() @Override
public String requestScheme()
{ {
this.scheme = null; return scheme;
this.remoteAddr = null;
this.requestURI = null;
} }


public ServerSession( String scheme, String remoteAddr, String requestURI ) @Override
public String clientAddress()
{ {
this.scheme = requireNonNull( scheme, "scheme" ); return String.format( "%s:%s", clientAddress.getHostString(), clientAddress.getPort() );
this.remoteAddr = requireNonNull( remoteAddr, "remoteAddr" );
this.requestURI = requireNonNull( requestURI, "requestURI" );
} }


@Override @Override
public String asConnectionDetails() public String requestURI()
{ {
return scheme == null ? "server-session" : String.join( "\t", return serverAddress == null ? requestPath : String.format(
"server-session", scheme, remoteAddr, requestURI ); "%s://%s:%d%s",
scheme,
serverAddress.getHostString(),
serverAddress.getPort(),
requestPath );
} }
} }


Expand Down Expand Up @@ -132,5 +197,23 @@ public String asConnectionDetails()
{ {
return source.asConnectionDetails() + '\t' + username; return source.asConnectionDetails() + '\t' + username;
} }

@Override
public String requestScheme()
{
return source.requestScheme();
}

@Override
public String clientAddress()
{
return source.clientAddress();
}

@Override
public String requestURI()
{
return source.requestURI();
}
} }
} }
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ public void connectionDetailsForHttpQuerySource() throws Exception
{ {
// given // given
QuerySource querySource = QuerySource querySource =
new QuerySource.ServerSession( "http", "127.0.0.1", "/db/data/transaction/45/commit" ) new QuerySource.ServerSession( "http", null,
new InetSocketAddress( "127.0.0.1", 1337 ), null, "/db/data/transaction/45/commit" )
.withUsername( "username" ); .withUsername( "username" );


// when // when
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -19,16 +19,22 @@
*/ */
package org.neo4j.server.rest.web; package org.neo4j.server.rest.web;


import java.net.InetSocketAddress;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;


import org.neo4j.kernel.impl.query.QuerySource; import org.neo4j.kernel.impl.query.QuerySource;


import static javax.ws.rs.core.HttpHeaders.USER_AGENT;

public class ServerQuerySession public class ServerQuerySession
{ {
public static QuerySource describe( HttpServletRequest request ) public static QuerySource describe( HttpServletRequest request )
{ {
return request == null ? return new QuerySource.ServerSession(
new QuerySource.ServerSession() : request.getScheme(),
new QuerySource.ServerSession( request.getScheme(), request.getRemoteAddr(), request.getRequestURI() ); request.getHeader( USER_AGENT ),
new InetSocketAddress( request.getRemoteAddr(), request.getRemotePort() ),
new InetSocketAddress( request.getServerName(), request.getServerPort() ),
request.getRequestURI() );
} }
} }
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -163,5 +163,11 @@ private void setUpMocks()
when( databaseQueryService.beginTransaction( type, securityContext, when( databaseQueryService.beginTransaction( type, securityContext,
CUSTOM_TRANSACTION_TIMEOUT, TimeUnit.MILLISECONDS ) ).thenReturn( transaction ); CUSTOM_TRANSACTION_TIMEOUT, TimeUnit.MILLISECONDS ) ).thenReturn( transaction );
when( databaseQueryService.getDependencyResolver() ).thenReturn( resolver ); when( databaseQueryService.getDependencyResolver() ).thenReturn( resolver );
when( request.getScheme() ).thenReturn( "http" );
when( request.getRemoteAddr() ).thenReturn( "127.0.0.1" );
when( request.getRemotePort() ).thenReturn( 5678 );
when( request.getServerName() ).thenReturn( "127.0.0.1" );
when( request.getServerPort() ).thenReturn( 7474 );
when( request.getRequestURI() ).thenReturn( "/" );
} }
} }
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;


public class CypherSessionTest public class CypherSessionTest
{ {
Expand All @@ -45,9 +46,16 @@ public void shouldReturnASingleNode() throws Throwable
Database database = new WrappedDatabase( graphdb ); Database database = new WrappedDatabase( graphdb );
CypherExecutor executor = new CypherExecutor( database, NullLogProvider.getInstance() ); CypherExecutor executor = new CypherExecutor( database, NullLogProvider.getInstance() );
executor.start(); executor.start();
HttpServletRequest request = mock( HttpServletRequest.class );
when( request.getScheme() ).thenReturn( "http" );
when( request.getRemoteAddr() ).thenReturn( "127.0.0.1" );
when( request.getRemotePort() ).thenReturn( 5678 );
when( request.getServerName() ).thenReturn( "127.0.0.1" );
when( request.getServerPort() ).thenReturn( 7474 );
when( request.getRequestURI() ).thenReturn( "/" );
try try
{ {
CypherSession session = new CypherSession( executor, NullLogProvider.getInstance(), mock( HttpServletRequest.class ) ); CypherSession session = new CypherSession( executor, NullLogProvider.getInstance(), request );
Pair<String, String> result = session.evaluate( "create (a) return a" ); Pair<String, String> result = session.evaluate( "create (a) return a" );
assertThat( result.first(), containsString( "Node[0]" ) ); assertThat( result.first(), containsString( "Node[0]" ) );
} }
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -43,11 +43,16 @@ public class QueryStatusResult
public final Map<String,Object> parameters; public final Map<String,Object> parameters;
public final String startTime; public final String startTime;
public final String elapsedTime; public final String elapsedTime;
/** EXPERIMENTAL: added in Neo4j 3.2 */
public final long elapsedTimeMillis; // TODO: this field should be of a Duration type (when Cypher supports that)
@Deprecated @Deprecated
public final String connectionDetails; public final String connectionDetails;
// public final String requestKey; /** EXPERIMENTAL: added in Neo4j 3.2 */
// public final String remoteAddress; public final String requestScheme;
// public final String requestUri; /** EXPERIMENTAL: added in Neo4j 3.2 */
public final String clientAddress;
/** EXPERIMENTAL: added in Neo4j 3.2 */
public final String requestURI;
/** EXPERIMENTAL: added in Neo4j 3.2 */ /** EXPERIMENTAL: added in Neo4j 3.2 */
public final long cpuTimeMillis; // TODO: we want this field to be of a Duration type (when Cypher supports that) public final long cpuTimeMillis; // TODO: we want this field to be of a Duration type (when Cypher supports that)
/** EXPERIMENTAL: added in Neo4j 3.2 */ /** EXPERIMENTAL: added in Neo4j 3.2 */
Expand Down Expand Up @@ -91,7 +96,11 @@ private QueryStatusResult(
this.parameters = parameters; this.parameters = parameters;
this.startTime = formatTime( startTime ); this.startTime = formatTime( startTime );
this.elapsedTime = formatInterval( elapsedTime ); this.elapsedTime = formatInterval( elapsedTime );
this.elapsedTimeMillis = elapsedTime;
this.connectionDetails = querySource.asConnectionDetails(); this.connectionDetails = querySource.asConnectionDetails();
this.requestScheme = querySource.requestScheme();
this.clientAddress = querySource.clientAddress();
this.requestURI = querySource.requestURI();
this.metaData = txMetaData; this.metaData = txMetaData;
this.cpuTimeMillis = cpuTimeMillis; this.cpuTimeMillis = cpuTimeMillis;
this.status = status; this.status = status;
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
*/ */
package org.neo4j.kernel.enterprise.builtinprocs; package org.neo4j.kernel.enterprise.builtinprocs;


import java.io.PrintWriter;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;


Expand All @@ -38,11 +37,11 @@
import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.hasKey;
import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.neo4j.test.rule.concurrent.ThreadingRule.waitingWhileIn; import static org.neo4j.test.rule.concurrent.ThreadingRule.waitingWhileIn;


public class ListQueriesProcedureTest public class ListQueriesProcedureTest
Expand Down Expand Up @@ -103,18 +102,21 @@ public void shouldProvideElapsedCpuTime() throws Exception
Map<String,Object> data = getQueryListing( "MATCH (n) SET n.v = n.v + 1" ); Map<String,Object> data = getQueryListing( "MATCH (n) SET n.v = n.v + 1" );


// then // then
assertTrue( "should contain a 'cpuTimeMillis' field", data.containsKey( "cpuTimeMillis" ) ); assertThat( data, hasKey( "elapsedTimeMillis" ) );
Object elapsedTime = data.get( "elapsedTimeMillis" );
assertThat( elapsedTime, instanceOf( Long.class ) );
assertThat( data, hasKey( "cpuTimeMillis" ) );
Object cpuTime1 = data.get( "cpuTimeMillis" ); Object cpuTime1 = data.get( "cpuTimeMillis" );
assertThat( cpuTime1, instanceOf( Long.class ) ); assertThat( cpuTime1, instanceOf( Long.class ) );
assertTrue( "should contain a 'status' field", data.containsKey( "status" ) ); assertThat( data, hasKey( "status" ) );
Object status = data.get( "status" ); Object status = data.get( "status" );
assertThat( status, instanceOf( Map.class ) ); assertThat( status, instanceOf( Map.class ) );
@SuppressWarnings( "unchecked" ) @SuppressWarnings( "unchecked" )
Map<String,Object> statusMap = (Map<String,Object>) status; Map<String,Object> statusMap = (Map<String,Object>) status;
assertEquals( "WAITING", statusMap.get( "state" ) ); assertEquals( "WAITING", statusMap.get( "state" ) );
assertEquals( "NODE", statusMap.get( "resourceType" ) ); assertEquals( "NODE", statusMap.get( "resourceType" ) );
assertArrayEquals( new long[]{node.getId()}, (long[]) statusMap.get( "resourceIds" ) ); assertArrayEquals( new long[]{node.getId()}, (long[]) statusMap.get( "resourceIds" ) );
assertTrue( "should contain a 'waitTimeMillis' field", data.containsKey( "waitTimeMillis" ) ); assertThat( data, hasKey( "waitTimeMillis" ) );
Object waitTime1 = data.get( "waitTimeMillis" ); Object waitTime1 = data.get( "waitTimeMillis" );
assertThat( waitTime1, instanceOf( Long.class ) ); assertThat( waitTime1, instanceOf( Long.class ) );


Expand All @@ -133,6 +135,18 @@ public void shouldProvideElapsedCpuTime() throws Exception
} }
} }


@Test
public void shouldContainSpecificConnectionDetails() throws Exception
{
// when
Map<String,Object> data = getQueryListing( "CALL dbms.listQueries" );

// then
assertThat( data, hasKey( "requestScheme" ) );
assertThat( data, hasKey( "clientAddress" ) );
assertThat( data, hasKey( "requestURI" ) );
}

private Map<String,Object> getQueryListing( String query ) private Map<String,Object> getQueryListing( String query )
{ {
try ( Result rows = db.execute( "CALL dbms.listQueries" ) ) try ( Result rows = db.execute( "CALL dbms.listQueries" ) )
Expand Down

0 comments on commit 5ce9180

Please sign in to comment.