Skip to content

Commit

Permalink
Fix bugs and clean code
Browse files Browse the repository at this point in the history
  • Loading branch information
Joshua Segaran committed Jun 17, 2020
1 parent 4cc1db4 commit dbbc7c8
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 12 deletions.
@@ -0,0 +1,124 @@
import {
Trace,
} from 'apollo-engine-reporting-protobuf';
import { dateToProtoTimestamp } from "../treeBuilder";
import { ContextualizedStats } from "../contextualizedStats";
import { DurationHistogram } from "../durationHistogram";

describe('Check query latency stats when', () => {
const statsContext = {
clientReferenceId: "reference",
clientVersion: "version"
}

let baseDate = new Date();
let nonFederatedTrace = new Trace({
startTime: dateToProtoTimestamp(baseDate),
endTime: dateToProtoTimestamp(new Date(baseDate.getTime() + 30*1000)),
durationNs: 30*1000,
root: null,
signature: "signature",
details: null,
});

it('adding a single trace', () => {
let contextualizedStats = new ContextualizedStats(statsContext);
contextualizedStats.addTrace(nonFederatedTrace);
expect(contextualizedStats.queryLatencyStats.requestCount).toBe(1);
expect(contextualizedStats.queryLatencyStats.latencyCount).toStrictEqual(new DurationHistogram().incrementDuration(30*1000));
expect(contextualizedStats.queryLatencyStats.requestsWithErrorsCount).toBe(0);
});
it('adding a fully cached trace', () => {
let contextualizedStats = new ContextualizedStats(statsContext);
contextualizedStats.addTrace(new Trace({
...nonFederatedTrace,
fullQueryCacheHit: true
}));
expect(contextualizedStats.queryLatencyStats.requestCount).toBe(1);
expect(contextualizedStats.queryLatencyStats.cacheHits).toBe(1);
expect(contextualizedStats.queryLatencyStats.cacheLatencyCount).toStrictEqual(new DurationHistogram().incrementDuration(30*1000));
});
it('adding a public cached trace', () => {
let contextualizedStats = new ContextualizedStats(statsContext);
contextualizedStats.addTrace(new Trace({
...nonFederatedTrace,
fullQueryCacheHit: false,
cachePolicy: {
scope: Trace.CachePolicy.Scope.PRIVATE,
maxAgeNs: 1000
}
}));
expect(contextualizedStats.queryLatencyStats.requestCount).toBe(1);
expect(contextualizedStats.queryLatencyStats.privateCacheTtlCount).toStrictEqual(new DurationHistogram().incrementDuration(1000));
});
it('adding a private cached trace', () => {
let contextualizedStats = new ContextualizedStats(statsContext);
contextualizedStats.addTrace(new Trace({
...nonFederatedTrace,
fullQueryCacheHit: false,
cachePolicy: {
scope: Trace.CachePolicy.Scope.PUBLIC,
maxAgeNs: 1000
}
}));
expect(contextualizedStats.queryLatencyStats.requestCount).toBe(1);
expect(contextualizedStats.queryLatencyStats.publicCacheTtlCount).toStrictEqual(new DurationHistogram().incrementDuration(1000));
});
it('adding a persisted hit trace', () => {
let contextualizedStats = new ContextualizedStats(statsContext);
contextualizedStats.addTrace(new Trace({
...nonFederatedTrace,
persistedQueryHit: true
}));
expect(contextualizedStats.queryLatencyStats.requestCount).toBe(1);
expect(contextualizedStats.queryLatencyStats.persistedQueryHits).toBe(1);
});
it('adding a persisted miss trace', () => {
let contextualizedStats = new ContextualizedStats(statsContext);
contextualizedStats.addTrace(new Trace({
...nonFederatedTrace,
persistedQueryRegister: true
}));
expect(contextualizedStats.queryLatencyStats.requestCount).toBe(1);
expect(contextualizedStats.queryLatencyStats.persistedQueryMisses).toBe(1);
});
it('adding a forbidden trace', () => {
let contextualizedStats = new ContextualizedStats(statsContext);
contextualizedStats.addTrace(new Trace({
...nonFederatedTrace,
forbiddenOperation: true,
}));
expect(contextualizedStats.queryLatencyStats.requestCount).toBe(1);
expect(contextualizedStats.queryLatencyStats.forbiddenOperationCount).toBe(1);
});
it('adding a registered trace', () => {
let contextualizedStats = new ContextualizedStats(statsContext);
contextualizedStats.addTrace(new Trace({
...nonFederatedTrace,
registeredOperation: true,
}));
expect(contextualizedStats.queryLatencyStats.requestCount).toBe(1);
expect(contextualizedStats.queryLatencyStats.registeredOperationCount).toBe(1);
});
it('adding an errored trace ', () => {
let contextualizedStats = new ContextualizedStats(statsContext);
contextualizedStats.addTrace(new Trace({
...nonFederatedTrace,
registeredOperation: true,
root: {
child: [{
responseName: "user",
parentType: "Query",
type: "User!",
error: [{
message: "error 1"
}]
}]
}
}));
expect(contextualizedStats.queryLatencyStats.requestCount).toBe(1);
console.log(contextualizedStats.queryLatencyStats.rootErrorStats);
expect(contextualizedStats.queryLatencyStats.rootErrorStats.children["user"].requestsWithErrorsCount).toBe(1);
expect(contextualizedStats.queryLatencyStats.rootErrorStats.children["user"].errorsCount).toBe(1);
});
})
4 changes: 3 additions & 1 deletion packages/apollo-engine-reporting/src/agent.ts
Expand Up @@ -32,7 +32,7 @@ import { reportingLoop, SchemaReporter } from './schemaReporter';
import { v4 as uuidv4 } from 'uuid';
import { createHash } from 'crypto';
import { DurationHistogram } from './durationHistogram';
import { ContextualizedStats } from './ContextualizedStats';
import { ContextualizedStats } from './contextualizedStats';

let warnedOnDeprecatedApiKey = false;

Expand Down Expand Up @@ -743,6 +743,8 @@ export class EngineReportingAgent<TContext = any> {

const statsKeys = Object.keys(report.tracesPerQuery);
for (const statsKey of statsKeys) {
// Take the contextualized stats from the map and push them onto the
// statsContext array
const statsMap: Map<IStatsContext, ContextualizedStats> = (report
.tracesPerQuery[statsKey] as any).statsMap;
if (statsMap) {
Expand Down
Expand Up @@ -45,14 +45,14 @@ export class ContextualizedStats {
);
}

if (!trace.fullQueryCacheHit && trace.cachePolicy && trace.cachePolicy) {
if (!trace.fullQueryCacheHit && trace.cachePolicy && trace.cachePolicy.maxAgeNs) {
if (trace.cachePolicy.scope == Trace.CachePolicy.Scope.PRIVATE) {
((queryLatencyStats.privateCacheTtlCount as unknown) as DurationHistogram).incrementDuration(
trace.cachePolicy.maxAgeNs || 0,
trace.cachePolicy.maxAgeNs
);
} else if (trace.cachePolicy.scope == Trace.CachePolicy.Scope.PUBLIC) {
((queryLatencyStats.publicCacheTtlCount as unknown) as DurationHistogram).incrementDuration(
trace.cachePolicy.maxAgeNs || 0,
trace.cachePolicy.maxAgeNs
);
}
}
Expand All @@ -69,13 +69,12 @@ export class ContextualizedStats {
queryLatencyStats.registeredOperationCount++;
}

queryLatencyStats.requestsWithErrorsCount++;

let hasError = false;
const typeStats = this.perTypeStat;
const rootPathErrorStats = queryLatencyStats.rootErrorStats as IPathErrorStats;

function traceNodeStats(node: Trace.INode, path: ReadonlyArray<string>) {
// Generate error stats and error path information
if (node.error && node.error.length > 0) {
hasError = true;

Expand All @@ -93,14 +92,16 @@ export class ContextualizedStats {
[k: string]: IPathErrorStats;
})[subPath];
if (!nextPathErrorStats) {
nextPathErrorStats = Object.create(null)(
children as { [k: string]: IPathErrorStats },
nextPathErrorStats = Object.create(null);
(
children as { [k: string]: IPathErrorStats }
)[subPath] = nextPathErrorStats;
}

// nextPathErrorStats be null or undefined
// nextPathErrorStats cannot be null or undefined
currPathErrorStats = nextPathErrorStats as IPathErrorStats;
}

currPathErrorStats.requestsWithErrorsCount =
(currPathErrorStats.requestsWithErrorsCount || 0) + 1;
currPathErrorStats.errorsCount =
Expand Down Expand Up @@ -223,7 +224,7 @@ function iterateOverTraceNode(
childPath = path.concat(child.responseName);
}

iterateOverTraceNode(node, childPath, f);
iterateOverTraceNode(child, childPath, f);
}
}
f(node, path);
Expand Down
3 changes: 2 additions & 1 deletion packages/apollo-engine-reporting/src/durationHistogram.ts
Expand Up @@ -39,8 +39,9 @@ export class DurationHistogram {
: unboundedBucket;
}

public incrementDuration(durationNs: number) {
public incrementDuration(durationNs: number): DurationHistogram {
this.incrementBucket(DurationHistogram.durationToBucket(durationNs));
return this;
}

public incrementBucket(bucket: number, value = 1) {
Expand Down
2 changes: 1 addition & 1 deletion packages/apollo-engine-reporting/src/treeBuilder.ts
Expand Up @@ -259,7 +259,7 @@ function errorToProtobufError(error: GraphQLError): Trace.Error {
}

// Converts a JS Date into a Timestamp.
function dateToProtoTimestamp(date: Date): google.protobuf.Timestamp {
export function dateToProtoTimestamp(date: Date): google.protobuf.Timestamp {
const totalMillis = +date;
const millis = totalMillis % 1000;
return new google.protobuf.Timestamp({
Expand Down

0 comments on commit dbbc7c8

Please sign in to comment.