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

Side by Side Diff: base/debug/trace_event_impl.cc

Issue 13590005: Add a ConvertableToTraceFormat type to the trace framework. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 8 months 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
« no previous file with comments | « base/debug/trace_event_impl.h ('k') | base/debug/trace_event_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/debug/trace_event_impl.h" 5 #include "base/debug/trace_event_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/debug/leak_annotations.h" 10 #include "base/debug/leak_annotations.h"
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 category_enabled_(NULL), 257 category_enabled_(NULL),
258 name_(NULL), 258 name_(NULL),
259 thread_id_(0), 259 thread_id_(0),
260 phase_(TRACE_EVENT_PHASE_BEGIN), 260 phase_(TRACE_EVENT_PHASE_BEGIN),
261 flags_(0) { 261 flags_(0) {
262 arg_names_[0] = NULL; 262 arg_names_[0] = NULL;
263 arg_names_[1] = NULL; 263 arg_names_[1] = NULL;
264 memset(arg_values_, 0, sizeof(arg_values_)); 264 memset(arg_values_, 0, sizeof(arg_values_));
265 } 265 }
266 266
267 TraceEvent::TraceEvent(int thread_id, 267 TraceEvent::TraceEvent(
268 TimeTicks timestamp, 268 int thread_id,
269 char phase, 269 TimeTicks timestamp,
270 const unsigned char* category_enabled, 270 char phase,
271 const char* name, 271 const unsigned char* category_enabled,
272 unsigned long long id, 272 const char* name,
273 int num_args, 273 unsigned long long id,
274 const char** arg_names, 274 int num_args,
275 const unsigned char* arg_types, 275 const char** arg_names,
276 const unsigned long long* arg_values, 276 const unsigned char* arg_types,
277 unsigned char flags) 277 const unsigned long long* arg_values,
278 scoped_ptr<ConvertableToTraceFormat> convertable_values[],
279 unsigned char flags)
278 : timestamp_(timestamp), 280 : timestamp_(timestamp),
279 id_(id), 281 id_(id),
280 category_enabled_(category_enabled), 282 category_enabled_(category_enabled),
281 name_(name), 283 name_(name),
282 thread_id_(thread_id), 284 thread_id_(thread_id),
283 phase_(phase), 285 phase_(phase),
284 flags_(flags) { 286 flags_(flags) {
285 // Clamp num_args since it may have been set by a third_party library. 287 // Clamp num_args since it may have been set by a third_party library.
286 num_args = (num_args > kTraceMaxNumArgs) ? kTraceMaxNumArgs : num_args; 288 num_args = (num_args > kTraceMaxNumArgs) ? kTraceMaxNumArgs : num_args;
287 int i = 0; 289 int i = 0;
288 for (; i < num_args; ++i) { 290 for (; i < num_args; ++i) {
289 arg_names_[i] = arg_names[i]; 291 arg_names_[i] = arg_names[i];
290 arg_values_[i].as_uint = arg_values[i];
291 arg_types_[i] = arg_types[i]; 292 arg_types_[i] = arg_types[i];
293
294 if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE)
295 convertable_values_[i].reset(convertable_values[i].release());
296 else
297 arg_values_[i].as_uint = arg_values[i];
292 } 298 }
293 for (; i < kTraceMaxNumArgs; ++i) { 299 for (; i < kTraceMaxNumArgs; ++i) {
294 arg_names_[i] = NULL; 300 arg_names_[i] = NULL;
295 arg_values_[i].as_uint = 0u; 301 arg_values_[i].as_uint = 0u;
302 convertable_values_[i].reset();
296 arg_types_[i] = TRACE_VALUE_TYPE_UINT; 303 arg_types_[i] = TRACE_VALUE_TYPE_UINT;
297 } 304 }
298 305
299 bool copy = !!(flags & TRACE_EVENT_FLAG_COPY); 306 bool copy = !!(flags & TRACE_EVENT_FLAG_COPY);
300 size_t alloc_size = 0; 307 size_t alloc_size = 0;
301 if (copy) { 308 if (copy) {
302 alloc_size += GetAllocLength(name); 309 alloc_size += GetAllocLength(name);
303 for (i = 0; i < num_args; ++i) { 310 for (i = 0; i < num_args; ++i) {
304 alloc_size += GetAllocLength(arg_names_[i]); 311 alloc_size += GetAllocLength(arg_names_[i]);
305 if (arg_types_[i] == TRACE_VALUE_TYPE_STRING) 312 if (arg_types_[i] == TRACE_VALUE_TYPE_STRING)
306 arg_types_[i] = TRACE_VALUE_TYPE_COPY_STRING; 313 arg_types_[i] = TRACE_VALUE_TYPE_COPY_STRING;
307 } 314 }
308 } 315 }
309 316
310 bool arg_is_copy[kTraceMaxNumArgs]; 317 bool arg_is_copy[kTraceMaxNumArgs];
311 for (i = 0; i < num_args; ++i) { 318 for (i = 0; i < num_args; ++i) {
319 // No copying of convertable types, we retain ownership.
320 if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE)
321 continue;
322
312 // We only take a copy of arg_vals if they are of type COPY_STRING. 323 // We only take a copy of arg_vals if they are of type COPY_STRING.
313 arg_is_copy[i] = (arg_types_[i] == TRACE_VALUE_TYPE_COPY_STRING); 324 arg_is_copy[i] = (arg_types_[i] == TRACE_VALUE_TYPE_COPY_STRING);
314 if (arg_is_copy[i]) 325 if (arg_is_copy[i])
315 alloc_size += GetAllocLength(arg_values_[i].as_string); 326 alloc_size += GetAllocLength(arg_values_[i].as_string);
316 } 327 }
317 328
318 if (alloc_size) { 329 if (alloc_size) {
319 parameter_copy_storage_ = new RefCountedString; 330 parameter_copy_storage_ = new RefCountedString;
320 parameter_copy_storage_->data().resize(alloc_size); 331 parameter_copy_storage_->data().resize(alloc_size);
321 char* ptr = string_as_array(&parameter_copy_storage_->data()); 332 char* ptr = string_as_array(&parameter_copy_storage_->data());
322 const char* end = ptr + alloc_size; 333 const char* end = ptr + alloc_size;
323 if (copy) { 334 if (copy) {
324 CopyTraceEventParameter(&ptr, &name_, end); 335 CopyTraceEventParameter(&ptr, &name_, end);
325 for (i = 0; i < num_args; ++i) 336 for (i = 0; i < num_args; ++i) {
337 if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE)
338 continue;
326 CopyTraceEventParameter(&ptr, &arg_names_[i], end); 339 CopyTraceEventParameter(&ptr, &arg_names_[i], end);
340 }
327 } 341 }
328 for (i = 0; i < num_args; ++i) { 342 for (i = 0; i < num_args; ++i) {
343 if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE)
344 continue;
329 if (arg_is_copy[i]) 345 if (arg_is_copy[i])
330 CopyTraceEventParameter(&ptr, &arg_values_[i].as_string, end); 346 CopyTraceEventParameter(&ptr, &arg_values_[i].as_string, end);
331 } 347 }
332 DCHECK_EQ(end, ptr) << "Overrun by " << ptr - end; 348 DCHECK_EQ(end, ptr) << "Overrun by " << ptr - end;
333 } 349 }
334 } 350 }
335 351
352 TraceEvent::TraceEvent(const TraceEvent& other)
353 : timestamp_(other.timestamp_),
354 id_(other.id_),
355 category_enabled_(other.category_enabled_),
356 name_(other.name_),
357 thread_id_(other.thread_id_),
358 phase_(other.phase_),
359 flags_(other.flags_) {
360 parameter_copy_storage_ = other.parameter_copy_storage_;
361
362 for (int i = 0; i < kTraceMaxNumArgs; ++i) {
363 arg_values_[i] = other.arg_values_[i];
364 arg_names_[i] = other.arg_names_[i];
365 arg_types_[i] = other.arg_types_[i];
366
367 if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE) {
368 convertable_values_[i].reset(
369 const_cast<TraceEvent*>(&other)->convertable_values_[i].release());
370 } else {
371 convertable_values_[i].reset();
372 }
373 }
374 }
375
376 TraceEvent& TraceEvent::operator=(const TraceEvent& other) {
377 if (this == &other)
378 return *this;
379
380 timestamp_ = other.timestamp_;
381 id_ = other.id_;
382 category_enabled_ = other.category_enabled_;
383 name_ = other.name_;
384 parameter_copy_storage_ = other.parameter_copy_storage_;
385 thread_id_ = other.thread_id_;
386 phase_ = other.phase_;
387 flags_ = other.flags_;
388
389 for (int i = 0; i < kTraceMaxNumArgs; ++i) {
390 arg_values_[i] = other.arg_values_[i];
391 arg_names_[i] = other.arg_names_[i];
392 arg_types_[i] = other.arg_types_[i];
393
394 if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE) {
395 convertable_values_[i].reset(
396 const_cast<TraceEvent*>(&other)->convertable_values_[i].release());
397 } else {
398 convertable_values_[i].reset();
399 }
400 }
401 return *this;
402 }
403
336 TraceEvent::~TraceEvent() { 404 TraceEvent::~TraceEvent() {
337 } 405 }
338 406
339 // static 407 // static
340 void TraceEvent::AppendValueAsJSON(unsigned char type, 408 void TraceEvent::AppendValueAsJSON(unsigned char type,
341 TraceEvent::TraceValue value, 409 TraceEvent::TraceValue value,
342 std::string* out) { 410 std::string* out) {
343 std::string::size_type start_pos; 411 std::string::size_type start_pos;
344 switch (type) { 412 switch (type) {
345 case TRACE_VALUE_TYPE_BOOL: 413 case TRACE_VALUE_TYPE_BOOL:
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 phase_, 464 phase_,
397 name_); 465 name_);
398 466
399 // Output argument names and values, stop at first NULL argument name. 467 // Output argument names and values, stop at first NULL argument name.
400 for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) { 468 for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) {
401 if (i > 0) 469 if (i > 0)
402 *out += ","; 470 *out += ",";
403 *out += "\""; 471 *out += "\"";
404 *out += arg_names_[i]; 472 *out += arg_names_[i];
405 *out += "\":"; 473 *out += "\":";
406 AppendValueAsJSON(arg_types_[i], arg_values_[i], out); 474
475 if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE)
476 convertable_values_[i]->AppendAsTraceFormat(out);
477 else
478 AppendValueAsJSON(arg_types_[i], arg_values_[i], out);
407 } 479 }
408 *out += "}"; 480 *out += "}";
409 481
410 // If id_ is set, print it out as a hex string so we don't loose any 482 // If id_ is set, print it out as a hex string so we don't loose any
411 // bits (it might be a 64-bit pointer). 483 // bits (it might be a 64-bit pointer).
412 if (flags_ & TRACE_EVENT_FLAG_HAS_ID) 484 if (flags_ & TRACE_EVENT_FLAG_HAS_ID)
413 StringAppendF(out, ",\"id\":\"%" PRIx64 "\"", static_cast<uint64>(id_)); 485 StringAppendF(out, ",\"id\":\"%" PRIx64 "\"", static_cast<uint64>(id_));
414 486
415 // Instant events also output their scope. 487 // Instant events also output their scope.
416 if (phase_ == TRACE_EVENT_PHASE_INSTANT) { 488 if (phase_ == TRACE_EVENT_PHASE_INSTANT) {
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 TRACE_EVENT_API_ATOMIC_LOAD(*bucket_data->bucket); 630 TRACE_EVENT_API_ATOMIC_LOAD(*bucket_data->bucket);
559 if (!category_and_name) 631 if (!category_and_name)
560 return; 632 return;
561 const char* const combined = 633 const char* const combined =
562 reinterpret_cast<const char* const>(category_and_name); 634 reinterpret_cast<const char* const>(category_and_name);
563 const char* category; 635 const char* category;
564 const char* name; 636 const char* name;
565 ExtractCategoryAndName(combined, &category, &name); 637 ExtractCategoryAndName(combined, &category, &name);
566 TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_SAMPLE, 638 TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_SAMPLE,
567 TraceLog::GetCategoryEnabled(category), 639 TraceLog::GetCategoryEnabled(category),
568 name, 640 name, 0, 0, NULL, NULL, NULL, NULL, 0);
569 0,
570 0,
571 NULL,
572 NULL,
573 NULL,
574 0);
575 } 641 }
576 642
577 void TraceSamplingThread::GetSamples() { 643 void TraceSamplingThread::GetSamples() {
578 for (size_t i = 0; i < sample_buckets_.size(); ++i) { 644 for (size_t i = 0; i < sample_buckets_.size(); ++i) {
579 TraceBucketData* bucket_data = &sample_buckets_[i]; 645 TraceBucketData* bucket_data = &sample_buckets_[i];
580 bucket_data->callback.Run(bucket_data); 646 bucket_data->callback.Run(bucket_data);
581 } 647 }
582 } 648 }
583 649
584 void TraceSamplingThread::RegisterSampleBucket( 650 void TraceSamplingThread::RegisterSampleBucket(
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after
1007 &(json_events_str_ptr->data())); 1073 &(json_events_str_ptr->data()));
1008 1074
1009 if (!previous_logged_events->HasMoreEvents()) 1075 if (!previous_logged_events->HasMoreEvents())
1010 break; 1076 break;
1011 } 1077 }
1012 1078
1013 cb.Run(json_events_str_ptr); 1079 cb.Run(json_events_str_ptr);
1014 } 1080 }
1015 } 1081 }
1016 1082
1017 void TraceLog::AddTraceEvent(char phase, 1083 void TraceLog::AddTraceEvent(
1018 const unsigned char* category_enabled, 1084 char phase,
1019 const char* name, 1085 const unsigned char* category_enabled,
1020 unsigned long long id, 1086 const char* name,
1021 int num_args, 1087 unsigned long long id,
1022 const char** arg_names, 1088 int num_args,
1023 const unsigned char* arg_types, 1089 const char** arg_names,
1024 const unsigned long long* arg_values, 1090 const unsigned char* arg_types,
1025 unsigned char flags) { 1091 const unsigned long long* arg_values,
1092 scoped_ptr<ConvertableToTraceFormat> convertable_values[],
1093 unsigned char flags) {
1026 int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); 1094 int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
1027 base::TimeTicks now = base::TimeTicks::NowFromSystemTraceTime(); 1095 base::TimeTicks now = base::TimeTicks::NowFromSystemTraceTime();
1028 AddTraceEventWithThreadIdAndTimestamp(phase, category_enabled, name, id, 1096 AddTraceEventWithThreadIdAndTimestamp(phase, category_enabled, name, id,
1029 thread_id, now, num_args, arg_names, 1097 thread_id, now, num_args, arg_names,
1030 arg_types, arg_values, flags); 1098 arg_types, arg_values,
1099 convertable_values, flags);
1031 } 1100 }
1032 1101
1033 void TraceLog::AddTraceEventWithThreadIdAndTimestamp( 1102 void TraceLog::AddTraceEventWithThreadIdAndTimestamp(
1034 char phase, 1103 char phase,
1035 const unsigned char* category_enabled, 1104 const unsigned char* category_enabled,
1036 const char* name, 1105 const char* name,
1037 unsigned long long id, 1106 unsigned long long id,
1038 int thread_id, 1107 int thread_id,
1039 const TimeTicks& timestamp, 1108 const TimeTicks& timestamp,
1040 int num_args, 1109 int num_args,
1041 const char** arg_names, 1110 const char** arg_names,
1042 const unsigned char* arg_types, 1111 const unsigned char* arg_types,
1043 const unsigned long long* arg_values, 1112 const unsigned long long* arg_values,
1113 scoped_ptr<ConvertableToTraceFormat> convertable_values[],
1044 unsigned char flags) { 1114 unsigned char flags) {
1045 DCHECK(name); 1115 DCHECK(name);
1046 1116
1047 if (flags & TRACE_EVENT_FLAG_MANGLE_ID) 1117 if (flags & TRACE_EVENT_FLAG_MANGLE_ID)
1048 id ^= process_id_hash_; 1118 id ^= process_id_hash_;
1049 1119
1050 #if defined(OS_ANDROID) 1120 #if defined(OS_ANDROID)
1051 SendToATrace(phase, GetCategoryName(category_enabled), name, id, 1121 SendToATrace(phase, GetCategoryName(category_enabled), name, id,
1052 num_args, arg_names, arg_types, arg_values, flags); 1122 num_args, arg_names, arg_types, arg_values, flags);
1053 #endif 1123 #endif
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1090 if (!found) { 1160 if (!found) {
1091 existing_name->second.push_back(','); 1161 existing_name->second.push_back(',');
1092 existing_name->second.append(new_name); 1162 existing_name->second.append(new_name);
1093 } 1163 }
1094 } 1164 }
1095 } 1165 }
1096 1166
1097 logged_events_->AddEvent(TraceEvent(thread_id, 1167 logged_events_->AddEvent(TraceEvent(thread_id,
1098 now, phase, category_enabled, name, id, 1168 now, phase, category_enabled, name, id,
1099 num_args, arg_names, arg_types, arg_values, 1169 num_args, arg_names, arg_types, arg_values,
1100 flags)); 1170 convertable_values, flags));
1101 1171
1102 if (logged_events_->IsFull()) 1172 if (logged_events_->IsFull())
1103 notifier.AddNotificationWhileLocked(TRACE_BUFFER_FULL); 1173 notifier.AddNotificationWhileLocked(TRACE_BUFFER_FULL);
1104 1174
1105 if (watch_category_ == category_enabled && watch_event_name_ == name) 1175 if (watch_category_ == category_enabled && watch_event_name_ == name)
1106 notifier.AddNotificationWhileLocked(EVENT_WATCH_NOTIFICATION); 1176 notifier.AddNotificationWhileLocked(EVENT_WATCH_NOTIFICATION);
1107 1177
1108 event_callback_copy = event_callback_; 1178 event_callback_copy = event_callback_;
1109 } // release lock 1179 } // release lock
1110 1180
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1177 if (!it->second.empty()) { 1247 if (!it->second.empty()) {
1178 int num_args = 1; 1248 int num_args = 1;
1179 const char* arg_name = "name"; 1249 const char* arg_name = "name";
1180 unsigned char arg_type; 1250 unsigned char arg_type;
1181 unsigned long long arg_value; 1251 unsigned long long arg_value;
1182 trace_event_internal::SetTraceValue(it->second, &arg_type, &arg_value); 1252 trace_event_internal::SetTraceValue(it->second, &arg_type, &arg_value);
1183 logged_events_->AddEvent(TraceEvent(it->first, 1253 logged_events_->AddEvent(TraceEvent(it->first,
1184 TimeTicks(), TRACE_EVENT_PHASE_METADATA, 1254 TimeTicks(), TRACE_EVENT_PHASE_METADATA,
1185 &g_category_enabled[g_category_metadata], 1255 &g_category_enabled[g_category_metadata],
1186 "thread_name", trace_event_internal::kNoEventId, 1256 "thread_name", trace_event_internal::kNoEventId,
1187 num_args, &arg_name, &arg_type, &arg_value, 1257 num_args, &arg_name, &arg_type, &arg_value, NULL,
1188 TRACE_EVENT_FLAG_NONE)); 1258 TRACE_EVENT_FLAG_NONE));
1189 } 1259 }
1190 } 1260 }
1191 } 1261 }
1192 1262
1193 void TraceLog::InstallWaitableEventForSamplingTesting( 1263 void TraceLog::InstallWaitableEventForSamplingTesting(
1194 WaitableEvent* waitable_event) { 1264 WaitableEvent* waitable_event) {
1195 sampling_thread_->InstallWaitableEventForSamplingTesting(waitable_event); 1265 sampling_thread_->InstallWaitableEventForSamplingTesting(waitable_event);
1196 } 1266 }
1197 1267
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1237 name_ = name; 1307 name_ = name;
1238 TRACE_EVENT_API_ADD_TRACE_EVENT( 1308 TRACE_EVENT_API_ADD_TRACE_EVENT(
1239 TRACE_EVENT_PHASE_BEGIN, // phase 1309 TRACE_EVENT_PHASE_BEGIN, // phase
1240 category_enabled_, // category enabled 1310 category_enabled_, // category enabled
1241 name, // name 1311 name, // name
1242 0, // id 1312 0, // id
1243 0, // num_args 1313 0, // num_args
1244 NULL, // arg_names 1314 NULL, // arg_names
1245 NULL, // arg_types 1315 NULL, // arg_types
1246 NULL, // arg_values 1316 NULL, // arg_values
1317 NULL, // convertable_values
1247 TRACE_EVENT_FLAG_NONE); // flags 1318 TRACE_EVENT_FLAG_NONE); // flags
1248 } else { 1319 } else {
1249 category_enabled_ = NULL; 1320 category_enabled_ = NULL;
1250 } 1321 }
1251 } 1322 }
1252 1323
1253 ScopedTrace::~ScopedTrace() { 1324 ScopedTrace::~ScopedTrace() {
1254 if (category_enabled_ && *category_enabled_) { 1325 if (category_enabled_ && *category_enabled_) {
1255 TRACE_EVENT_API_ADD_TRACE_EVENT( 1326 TRACE_EVENT_API_ADD_TRACE_EVENT(
1256 TRACE_EVENT_PHASE_END, // phase 1327 TRACE_EVENT_PHASE_END, // phase
1257 category_enabled_, // category enabled 1328 category_enabled_, // category enabled
1258 name_, // name 1329 name_, // name
1259 0, // id 1330 0, // id
1260 0, // num_args 1331 0, // num_args
1261 NULL, // arg_names 1332 NULL, // arg_names
1262 NULL, // arg_types 1333 NULL, // arg_types
1263 NULL, // arg_values 1334 NULL, // arg_values
1335 NULL, // convertable values
1264 TRACE_EVENT_FLAG_NONE); // flags 1336 TRACE_EVENT_FLAG_NONE); // flags
1265 } 1337 }
1266 } 1338 }
1267 1339
1268 } // namespace trace_event_internal 1340 } // namespace trace_event_internal
1269 1341
OLDNEW
« no previous file with comments | « base/debug/trace_event_impl.h ('k') | base/debug/trace_event_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698