src/Pure/Tools/build_log.scala
changeset 64119 8094eaa38d4b
parent 64117 c2b41b073d8a
child 64120 6c5039016321
equal deleted inserted replaced
64118:0996fab2ec03 64119:8094eaa38d4b
   134     }
   134     }
   135 
   135 
   136 
   136 
   137     /* inlined content */
   137     /* inlined content */
   138 
   138 
   139     def print_props(prefix: String, props: Properties.T): String =
   139     def print_props(marker: String, props: Properties.T): String =
   140       prefix + YXML.string_of_body(XML.Encode.properties(props))
   140       marker + YXML.string_of_body(XML.Encode.properties(props))
   141   }
   141   }
   142 
   142 
   143   class Log_File private(val name: String, val lines: List[String])
   143   class Log_File private(val name: String, val lines: List[String])
   144   {
   144   {
   145     log_file =>
   145     log_file =>
   189     val xml_cache = new XML.Cache()
   189     val xml_cache = new XML.Cache()
   190 
   190 
   191     def parse_props(text: String): Properties.T =
   191     def parse_props(text: String): Properties.T =
   192       xml_cache.props(XML.Decode.properties(YXML.parse_body(text)))
   192       xml_cache.props(XML.Decode.properties(YXML.parse_body(text)))
   193 
   193 
   194     def filter_props(prefix: String): List[Properties.T] =
   194     def filter_props(marker: String): List[Properties.T] =
   195       for (line <- lines; s <- Library.try_unprefix(prefix, line)) yield parse_props(s)
   195       for (line <- lines; s <- Library.try_unprefix(marker, line)) yield parse_props(s)
   196 
   196 
   197     def find_line(prefix: String): Option[String] =
   197     def find_line(marker: String): Option[String] =
   198       find(Library.try_unprefix(prefix, _))
   198       find(Library.try_unprefix(marker, _))
   199 
   199 
   200     def find_props(prefix: String): Option[Properties.T] =
   200     def find_props(marker: String): Option[Properties.T] =
   201       find_line(prefix).map(parse_props(_))
   201       find_line(marker).map(parse_props(_))
   202 
   202 
   203 
   203 
   204     /* parse various formats */
   204     /* parse various formats */
   205 
   205 
   206     def parse_meta_info(): Meta_Info = Build_Log.parse_meta_info(log_file)
   206     def parse_meta_info(): Meta_Info = Build_Log.parse_meta_info(log_file)
   298           start_date ::: end_date ::: isabelle_version.toList ::: afp_version.toList,
   298           start_date ::: end_date ::: isabelle_version.toList ::: afp_version.toList,
   299         log_file.get_settings(Settings.all_settings))
   299         log_file.get_settings(Settings.all_settings))
   300     }
   300     }
   301 
   301 
   302     log_file.lines match {
   302     log_file.lines match {
   303       case line :: _ if line.startsWith(Build_History.META_INFO) =>
   303       case line :: _ if line.startsWith(Build_History.META_INFO_MARKER) =>
   304         Meta_Info(log_file.find_props(Build_History.META_INFO).get,
   304         Meta_Info(log_file.find_props(Build_History.META_INFO_MARKER).get,
   305           log_file.get_settings(Settings.all_settings))
   305           log_file.get_settings(Settings.all_settings))
   306 
   306 
   307       case Isatest.Start(log_file.Strict_Date(start), host) :: _ =>
   307       case Isatest.Start(log_file.Strict_Date(start), host) :: _ =>
   308         parse(Isatest.engine, host, start, Isatest.End,
   308         parse(Isatest.engine, host, start, Isatest.End,
   309           Isatest.Isabelle_Version, Isatest.No_AFP_Version)
   309           Isatest.Isabelle_Version, Isatest.No_AFP_Version)
   335     }
   335     }
   336   }
   336   }
   337 
   337 
   338 
   338 
   339 
   339 
   340   /** build info: produced by isabelle build **/
   340   /** build info: produced by isabelle build or build_history **/
       
   341 
       
   342   val ML_STATISTICS_MARKER = "\fML_statistics = "
       
   343   val SESSION_NAME = "session_name"
   341 
   344 
   342   object Session_Status extends Enumeration
   345   object Session_Status extends Enumeration
   343   {
   346   {
   344     val EXISTING = Value("existing")
   347     val EXISTING = Value("existing")
   345     val FINISHED = Value("finished")
   348     val FINISHED = Value("finished")
   351     chapter: String,
   354     chapter: String,
   352     groups: List[String],
   355     groups: List[String],
   353     threads: Option[Int],
   356     threads: Option[Int],
   354     timing: Timing,
   357     timing: Timing,
   355     ml_timing: Timing,
   358     ml_timing: Timing,
       
   359     ml_statistics: List[Properties.T],
   356     status: Session_Status.Value)
   360     status: Session_Status.Value)
   357   {
   361   {
   358     def finished: Boolean = status == Session_Status.FINISHED
   362     def finished: Boolean = status == Session_Status.FINISHED
   359   }
   363   }
   360 
   364 
   367       get_session(name) match {
   371       get_session(name) match {
   368         case Some(entry) => f(entry)
   372         case Some(entry) => f(entry)
   369         case None => x
   373         case None => x
   370       }
   374       }
   371 
   375 
       
   376     def finished_sessions: List[String] = sessions.keySet.iterator.filter(finished(_)).toList
   372     def finished(name: String): Boolean = get_default(name, _.finished, false)
   377     def finished(name: String): Boolean = get_default(name, _.finished, false)
   373     def timing(name: String): Timing = get_default(name, _.timing, Timing.zero)
   378     def timing(name: String): Timing = get_default(name, _.timing, Timing.zero)
   374     def ml_timing(name: String): Timing = get_default(name, _.ml_timing, Timing.zero)
   379     def ml_timing(name: String): Timing = get_default(name, _.ml_timing, Timing.zero)
   375   }
   380   }
   376 
   381 
   403     var timing = Map.empty[String, Timing]
   408     var timing = Map.empty[String, Timing]
   404     var ml_timing = Map.empty[String, Timing]
   409     var ml_timing = Map.empty[String, Timing]
   405     var started = Set.empty[String]
   410     var started = Set.empty[String]
   406     var failed = Set.empty[String]
   411     var failed = Set.empty[String]
   407     var cancelled = Set.empty[String]
   412     var cancelled = Set.empty[String]
       
   413     var ml_statistics = Map.empty[String, List[Properties.T]]
       
   414 
   408     def all_sessions: Set[String] =
   415     def all_sessions: Set[String] =
   409       chapter.keySet ++ groups.keySet ++ threads.keySet ++
   416       chapter.keySet ++ groups.keySet ++ threads.keySet ++ timing.keySet ++
   410       timing.keySet ++ ml_timing.keySet ++ failed ++ cancelled ++ started
   417       ml_timing.keySet ++ failed ++ cancelled ++ started ++ ml_statistics.keySet
   411 
   418 
   412 
   419 
   413     for (line <- log_file.lines) {
   420     for (line <- log_file.lines) {
   414       line match {
   421       line match {
   415         case Session_No_Groups(Chapter_Name(chapt, name)) =>
   422         case Session_No_Groups(Chapter_Name(chapt, name)) =>
   416           chapter += (name -> chapt)
   423           chapter += (name -> chapt)
   417           groups += (name -> Nil)
   424           groups += (name -> Nil)
       
   425 
   418         case Session_Groups(Chapter_Name(chapt, name), grps) =>
   426         case Session_Groups(Chapter_Name(chapt, name), grps) =>
   419           chapter += (name -> chapt)
   427           chapter += (name -> chapt)
   420           groups += (name -> Word.explode(grps))
   428           groups += (name -> Word.explode(grps))
       
   429 
   421         case Session_Started(name) =>
   430         case Session_Started(name) =>
   422           started += name
   431           started += name
       
   432 
   423         case Session_Finished1(name,
   433         case Session_Finished1(name,
   424             Value.Int(e1), Value.Int(e2), Value.Int(e3),
   434             Value.Int(e1), Value.Int(e2), Value.Int(e3),
   425             Value.Int(c1), Value.Int(c2), Value.Int(c3)) =>
   435             Value.Int(c1), Value.Int(c2), Value.Int(c3)) =>
   426           val elapsed = Time.hms(e1, e2, e3)
   436           val elapsed = Time.hms(e1, e2, e3)
   427           val cpu = Time.hms(c1, c2, c3)
   437           val cpu = Time.hms(c1, c2, c3)
   428           timing += (name -> Timing(elapsed, cpu, Time.zero))
   438           timing += (name -> Timing(elapsed, cpu, Time.zero))
       
   439 
   429         case Session_Finished2(name,
   440         case Session_Finished2(name,
   430             Value.Int(e1), Value.Int(e2), Value.Int(e3)) =>
   441             Value.Int(e1), Value.Int(e2), Value.Int(e3)) =>
   431           val elapsed = Time.hms(e1, e2, e3)
   442           val elapsed = Time.hms(e1, e2, e3)
   432           timing += (name -> Timing(elapsed, Time.zero, Time.zero))
   443           timing += (name -> Timing(elapsed, Time.zero, Time.zero))
       
   444 
   433         case Session_Timing(name,
   445         case Session_Timing(name,
   434             Value.Int(t), Value.Double(e), Value.Double(c), Value.Double(g)) =>
   446             Value.Int(t), Value.Double(e), Value.Double(c), Value.Double(g)) =>
   435           val elapsed = Time.seconds(e)
   447           val elapsed = Time.seconds(e)
   436           val cpu = Time.seconds(c)
   448           val cpu = Time.seconds(c)
   437           val gc = Time.seconds(g)
   449           val gc = Time.seconds(g)
   438           ml_timing += (name -> Timing(elapsed, cpu, gc))
   450           ml_timing += (name -> Timing(elapsed, cpu, gc))
   439           threads += (name -> t)
   451           threads += (name -> t)
       
   452 
       
   453         case _ if line.startsWith(ML_STATISTICS_MARKER) =>
       
   454           val (name, props) =
       
   455             Library.try_unprefix(ML_STATISTICS_MARKER, line).map(log_file.parse_props(_)) match {
       
   456               case Some((SESSION_NAME, session_name) :: props) => (session_name, props)
       
   457               case _ => log_file.err("malformed ML_statistics " + quote(line))
       
   458             }
       
   459           ml_statistics = ml_statistics + (name -> (props :: ml_statistics.getOrElse(name, Nil)))
       
   460 
   440         case _ =>
   461         case _ =>
   441       }
   462       }
   442     }
   463     }
   443 
   464 
   444     val sessions =
   465     val sessions =
   456               chapter.getOrElse(name, ""),
   477               chapter.getOrElse(name, ""),
   457               groups.getOrElse(name, Nil),
   478               groups.getOrElse(name, Nil),
   458               threads.get(name),
   479               threads.get(name),
   459               timing.getOrElse(name, Timing.zero),
   480               timing.getOrElse(name, Timing.zero),
   460               ml_timing.getOrElse(name, Timing.zero),
   481               ml_timing.getOrElse(name, Timing.zero),
       
   482               ml_statistics.getOrElse(name, Nil).reverse,
   461               status)
   483               status)
   462           (name -> entry)
   484           (name -> entry)
   463         }):_*)
   485         }):_*)
   464     Build_Info(sessions)
   486     Build_Info(sessions)
   465   }
   487   }
   492       }
   514       }
   493     val session_timing = log_file.find_props("\fTiming = ") getOrElse Nil
   515     val session_timing = log_file.find_props("\fTiming = ") getOrElse Nil
   494     val command_timings_ =
   516     val command_timings_ =
   495       if (command_timings) log_file.filter_props("\fcommand_timing = ") else Nil
   517       if (command_timings) log_file.filter_props("\fcommand_timing = ") else Nil
   496     val ml_statistics_ =
   518     val ml_statistics_ =
   497       if (ml_statistics) log_file.filter_props("\fML_statistics = ") else Nil
   519       if (ml_statistics) log_file.filter_props(ML_STATISTICS_MARKER) else Nil
   498     val task_statistics_ =
   520     val task_statistics_ =
   499       if (task_statistics) log_file.filter_props("\ftask_statistics = ") else Nil
   521       if (task_statistics) log_file.filter_props("\ftask_statistics = ") else Nil
   500 
   522 
   501     Session_Info(session_name, session_timing, command_timings_, ml_statistics_, task_statistics_)
   523     Session_Info(session_name, session_timing, command_timings_, ml_statistics_, task_statistics_)
   502   }
   524   }