Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(370)

Side by Side Diff: pkg/analysis_server/lib/src/domain_diagnostic.dart

Issue 1509033003: Promote `diagnostic.getDiagnostics()` (#25061). (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library analysis_server.src.domain_diagnostic; 5 library analysis_server.src.domain_diagnostic;
6 6
7 import 'dart:async';
8 import 'dart:collection'; 7 import 'dart:collection';
9 import 'dart:core' hide Resource; 8 import 'dart:core' hide Resource;
10 9
11 import 'package:analysis_server/plugin/protocol/protocol.dart'; 10 import 'package:analysis_server/plugin/protocol/protocol.dart';
12 import 'package:analysis_server/src/analysis_server.dart'; 11 import 'package:analysis_server/src/analysis_server.dart';
13 import 'package:analysis_server/src/utilities/average.dart';
14 import 'package:analyzer/file_system/file_system.dart'; 12 import 'package:analyzer/file_system/file_system.dart';
15 import 'package:analyzer/src/context/cache.dart'; 13 import 'package:analyzer/src/context/cache.dart';
16 import 'package:analyzer/src/context/context.dart'; 14 import 'package:analyzer/src/context/context.dart';
17 import 'package:analyzer/src/generated/engine.dart'; 15 import 'package:analyzer/src/generated/engine.dart';
18 import 'package:analyzer/src/generated/source.dart'; 16 import 'package:analyzer/src/generated/source.dart';
19 import 'package:analyzer/src/generated/utilities_collection.dart'; 17 import 'package:analyzer/src/generated/utilities_collection.dart';
20 import 'package:analyzer/src/task/driver.dart'; 18 import 'package:analyzer/src/task/driver.dart';
21 import 'package:analyzer/task/model.dart'; 19 import 'package:analyzer/task/model.dart';
22 20
23 int _workItemCount(AnalysisContextImpl context) { 21 int _workItemCount(AnalysisContextImpl context) {
24 AnalysisDriver driver = context.driver; 22 AnalysisDriver driver = context.driver;
25 List<WorkItem> items = driver.currentWorkOrder?.workItems; 23 List<WorkItem> items = driver.currentWorkOrder?.workItems;
26 return items?.length ?? 0; 24 return items?.length ?? 0;
27 } 25 }
28 26
29 /// Instances of the class [DiagnosticDomainHandler] implement a 27 /// Instances of the class [DiagnosticDomainHandler] implement a
30 /// [RequestHandler] that handles requests in the `diagnostic` domain. 28 /// [RequestHandler] that handles requests in the `diagnostic` domain.
31 class DiagnosticDomainHandler implements RequestHandler { 29 class DiagnosticDomainHandler implements RequestHandler {
32 /// The name of the request used to get diagnostic information. 30 /// The name of the request used to get diagnostic information.
33 static const String DIAGNOSTICS = 'diagnostic.getDiagnostics'; 31 static const String DIAGNOSTICS = 'diagnostic.getDiagnostics';
34 32
35 /// The analysis server that is using this handler to process requests. 33 /// The analysis server that is using this handler to process requests.
36 final AnalysisServer server; 34 final AnalysisServer server;
37 35
38 /// The sampler tracking rolling work queue length averages.
39 Sampler sampler;
40
41 /// Initialize a newly created handler to handle requests for the given 36 /// Initialize a newly created handler to handle requests for the given
42 /// [server]. 37 /// [server].
43 DiagnosticDomainHandler(this.server); 38 DiagnosticDomainHandler(this.server);
44 39
45 /// Answer the `diagnostic.diagnostics` request. 40 /// Answer the `diagnostic.diagnostics` request.
46 Response computeDiagnostics(Request request) { 41 Response computeDiagnostics(Request request) {
47 // Initialize sampler if needed.
48 if (sampler == null) {
49 sampler = new Sampler(server);
50 }
51
52 List<ContextData> infos = <ContextData>[]; 42 List<ContextData> infos = <ContextData>[];
53 server.folderMap.forEach((Folder folder, AnalysisContext context) { 43 server.folderMap.forEach((Folder folder, AnalysisContext context) {
54 infos.add(extractData(folder, context)); 44 infos.add(extractData(folder, context));
55 }); 45 });
56 46
57 return new DiagnosticGetDiagnosticsResult(infos).toResponse(request.id); 47 return new DiagnosticGetDiagnosticsResult(infos).toResponse(request.id);
58 } 48 }
59 49
60 /// Extract context data from the given [context]. 50 /// Extract context data from the given [context].
61 ContextData extractData(Folder folder, AnalysisContext context) { 51 ContextData extractData(Folder folder, AnalysisContext context) {
62 int explicitFiles = 0; 52 int explicitFiles = 0;
63 int implicitFiles = 0; 53 int implicitFiles = 0;
64 int workItems = 0; 54 int workItems = 0;
65 String workItemAverage = '-1';
66 Set<String> exceptions = new HashSet<String>(); 55 Set<String> exceptions = new HashSet<String>();
67 if (context is AnalysisContextImpl) { 56 if (context is AnalysisContextImpl) {
68 workItems = _workItemCount(context); 57 workItems = _workItemCount(context);
69 workItemAverage = sampler.getAverage(folder)?.toString() ?? '-1';
70 var cache = context.analysisCache; 58 var cache = context.analysisCache;
71 if (cache is AnalysisCache) { 59 if (cache is AnalysisCache) {
72 Set<AnalysisTarget> countedTargets = new HashSet<AnalysisTarget>(); 60 Set<AnalysisTarget> countedTargets = new HashSet<AnalysisTarget>();
73 MapIterator<AnalysisTarget, CacheEntry> iterator = cache.iterator(); 61 MapIterator<AnalysisTarget, CacheEntry> iterator = cache.iterator();
74 while (iterator.moveNext()) { 62 while (iterator.moveNext()) {
75 AnalysisTarget target = iterator.key; 63 AnalysisTarget target = iterator.key;
76 if (countedTargets.add(target)) { 64 if (countedTargets.add(target)) {
77 CacheEntry cacheEntry = iterator.value; 65 CacheEntry cacheEntry = iterator.value;
78 if (target is Source) { 66 if (target is Source) {
79 if (cacheEntry.explicitlyAdded) { 67 if (cacheEntry.explicitlyAdded) {
80 explicitFiles++; 68 explicitFiles++;
81 } else { 69 } else {
82 implicitFiles++; 70 implicitFiles++;
83 } 71 }
84 } 72 }
85 // Caught exceptions. 73 // Caught exceptions.
86 if (cacheEntry.exception != null) { 74 if (cacheEntry.exception != null) {
87 exceptions.add(cacheEntry.exception.toString()); 75 exceptions.add(cacheEntry.exception.toString());
88 } 76 }
89 } 77 }
90 } 78 }
91 } 79 }
92 } 80 }
93 return new ContextData(context.name, explicitFiles, implicitFiles, 81 return new ContextData(context.name, explicitFiles, implicitFiles,
94 workItems, workItemAverage, exceptions.toList()); 82 workItems, exceptions.toList());
95 } 83 }
96 84
97 @override 85 @override
98 Response handleRequest(Request request) { 86 Response handleRequest(Request request) {
99 try { 87 try {
100 String requestName = request.method; 88 String requestName = request.method;
101 if (requestName == DIAGNOSTICS) { 89 if (requestName == DIAGNOSTICS) {
102 return computeDiagnostics(request); 90 return computeDiagnostics(request);
103 } 91 }
104 } on RequestFailure catch (exception) { 92 } on RequestFailure catch (exception) {
105 return exception.response; 93 return exception.response;
106 } 94 }
107 return null; 95 return null;
108 } 96 }
109 } 97 }
110
111 /// Keeps track of a moving average of work item queue lengths mapped to
112 /// contexts.
113 ///
114 /// Sampling terminates after [maxSampleCount], if no one expresses interest
115 /// by calling [resetTimerCountdown].
116 class Sampler {
117 /// Timer interval.
118 static const Duration duration = const Duration(seconds: 1);
119
120 /// Maximum number of samples taken between calls to [reset].
121 static const int maxSampleCount = 30;
122
123 /// Current sample count.
124 int sampleCount = 0;
125
126 /// The shared timer.
127 Timer timer;
128
129 /// Map of contexts (tracked as folders to avoid leaks) to averages.
130 /// TOOD(pq): consider adding GC to remove mappings for deleted folders
131 Map<Folder, Average> averages = new HashMap<Folder, Average>();
132
133 final AnalysisServer server;
134 Sampler(this.server) {
135 start();
136 _sample();
137 }
138
139 /// Get the average for the context associated with the given [folder].
140 num getAverage(Folder folder) {
141 resetTimerCountdown();
142 return averages[folder].value;
143 }
144
145 /// Check if we're currently sampling.
146 bool isSampling() => timer?.isActive ?? false;
147
148 /// Reset counter.
149 void resetTimerCountdown() {
150 sampleCount = 0;
151 }
152
153 /// Start sampling.
154 void start() {
155 // No need to (re)start if already sampling.
156 if (isSampling()) {
157 return;
158 }
159 timer = new Timer.periodic(duration, (Timer timer) {
160 _sample();
161 if (sampleCount++ >= maxSampleCount) {
162 timer.cancel();
163 }
164 });
165 }
166
167 /// Stop sampling.
168 void stop() {
169 timer.cancel();
170 }
171
172 /// Take a sample.
173 void _sample() {
174 try {
175 server.folderMap.forEach((Folder folder, AnalysisContext context) {
176 if (context is AnalysisContextImpl) {
177 Average average = averages[folder];
178 if (average == null) {
179 average = new Average();
180 averages[folder] = average;
181 }
182 average.addSample(_workItemCount(context));
183 }
184 });
185 } on Exception {
186 stop();
187 }
188 }
189 }
OLDNEW
« no previous file with comments | « pkg/analysis_server/lib/plugin/protocol/generated_protocol.dart ('k') | pkg/analysis_server/test/domain_diagnostic_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698