forked from MapComplete/MapComplete
		
	Improve error reporting, first attempt for script which handles the errors
This commit is contained in:
		
							parent
							
								
									b4ffdbd942
								
							
						
					
					
						commit
						4ef3429c5a
					
				
					 6 changed files with 117 additions and 11 deletions
				
			
		|  | @ -1,6 +1,6 @@ | |||
| { | ||||
|   "name": "mapcomplete", | ||||
|   "version": "0.44.4", | ||||
|   "version": "0.44.5", | ||||
|   "repository": "https://github.com/pietervdvn/MapComplete", | ||||
|   "description": "A small website to edit OSM easily", | ||||
|   "bugs": "https://github.com/pietervdvn/MapComplete/issues", | ||||
|  |  | |||
							
								
								
									
										100
									
								
								scripts/handleErrors.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								scripts/handleErrors.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,100 @@ | |||
| import Script from "./Script" | ||||
| import { readFileSync, writeFileSync } from "fs" | ||||
| import { ChangeDescription } from "../src/Logic/Osm/Actions/ChangeDescription" | ||||
| import { Changes } from "../src/Logic/Osm/Changes" | ||||
| import { OsmObject } from "../src/Logic/Osm/OsmObject" | ||||
| import OsmObjectDownloader from "../src/Logic/Osm/OsmObjectDownloader" | ||||
| import { OsmConnection } from "../src/Logic/Osm/OsmConnection" | ||||
| import { ImmutableStore } from "../src/Logic/UIEventSource" | ||||
| import { Utils } from "../src/Utils" | ||||
| 
 | ||||
| class HandleErrors extends Script { | ||||
| 
 | ||||
|     constructor() { | ||||
|         super("Inspects the errors made on a given day. Argument: path to errors") | ||||
|     } | ||||
| 
 | ||||
|     async main(args: string[]): Promise<void> { | ||||
|         const osmConnection = new OsmConnection() | ||||
|         const downloader = new OsmObjectDownloader(osmConnection.Backend(), undefined) | ||||
| 
 | ||||
|         const path = args[0] | ||||
|         const lines = readFileSync(path, "utf8").split("\n") | ||||
| 
 | ||||
|         for (const line of lines) { | ||||
|             if (!line?.trim()) { | ||||
|                 continue | ||||
|             } | ||||
|             try { | ||||
| 
 | ||||
|                 const parsed: { | ||||
|                     ip: string, index: number, date: string, | ||||
|                     message: { | ||||
|                         stacktrace: string | ||||
|                         message: string | ||||
|                         layout: string | ||||
|                         version: string | ||||
|                         language: string | ||||
|                         username: string | ||||
|                         userid: number | ||||
|                         pendingChanges: ChangeDescription[] | ||||
|                     } | ||||
|                 } = JSON.parse(line) | ||||
|                 const e = parsed.message | ||||
|                 if (e.layout !== "grb") { | ||||
|                     continue | ||||
|                 } | ||||
|                 console.log(e.username, e.layout, e.message, parsed.date) | ||||
|                 for (const pendingChange of e.pendingChanges) { | ||||
|                     console.log("\t https://osm.org/" + pendingChange.type + "/" + pendingChange.id, pendingChange.meta.changeType, pendingChange.doDelete ? "DELETE" : "") | ||||
|                 } | ||||
| 
 | ||||
| 
 | ||||
|                 const neededIds = Changes.GetNeededIds(e.pendingChanges) | ||||
|                 // We _do not_ pass in the Changes object itself - we want the data from OSM directly in order to apply the changes
 | ||||
|                 let osmObjects: { id: string, osmObj: OsmObject | "deleted" }[] = await Promise.all<{ | ||||
|                     id: string; | ||||
|                     osmObj: OsmObject | "deleted" | ||||
|                 }>( | ||||
|                     neededIds.map(async id => ({ id, osmObj: await downloader.DownloadObjectAsync(id) })), | ||||
|                 ) | ||||
| 
 | ||||
|                 const objects = osmObjects | ||||
|                     .filter((obj) => obj.osmObj !== "deleted") | ||||
|                     .map((obj) => <OsmObject>obj.osmObj) | ||||
| 
 | ||||
|                 const perType = Array.from( | ||||
|                     Utils.Hist( | ||||
|                         e.pendingChanges | ||||
|                             .filter( | ||||
|                                 (descr) => | ||||
|                                     descr.meta.changeType !== undefined && descr.meta.changeType !== null, | ||||
|                             ) | ||||
|                             .map((descr) => descr.meta.changeType), | ||||
|                     ), | ||||
|                     ([key, count]) => ({ | ||||
|                         key: key, | ||||
|                         value: count, | ||||
|                         aggregate: true, | ||||
|                     }), | ||||
|                 ) | ||||
|                 const changes: { | ||||
|                     newObjects: OsmObject[] | ||||
|                     modifiedObjects: OsmObject[] | ||||
|                     deletedObjects: OsmObject[] | ||||
|                 } = new Changes({ | ||||
|                     dryRun: new ImmutableStore(true), | ||||
|                     osmConnection, | ||||
|                 }).CreateChangesetObjects(e.pendingChanges, objects) | ||||
| 
 | ||||
|                 const changeset = Changes.createChangesetFor("" + parsed.index, changes) | ||||
|                 writeFileSync("error_changeset_"+parsed.index+".osc", changeset, "utf8") | ||||
|             } catch (e) { | ||||
|                 console.log("Parsing line failed:", e) | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| new HandleErrors().run() | ||||
|  | @ -13,10 +13,6 @@ import { ChangesetHandler, ChangesetTag } from "./ChangesetHandler" | |||
| import { OsmConnection } from "./OsmConnection" | ||||
| import FeaturePropertiesStore from "../FeatureSource/Actors/FeaturePropertiesStore" | ||||
| import OsmObjectDownloader from "./OsmObjectDownloader" | ||||
| import Combine from "../../UI/Base/Combine" | ||||
| import BaseUIElement from "../../UI/BaseUIElement" | ||||
| import Title from "../../UI/Base/Title" | ||||
| import Table from "../../UI/Base/Table" | ||||
| import ChangeLocationAction from "./Actions/ChangeLocationAction" | ||||
| import ChangeTagAction from "./Actions/ChangeTagAction" | ||||
| import FeatureSwitchState from "../State/FeatureSwitchState" | ||||
|  | @ -44,7 +40,7 @@ export class Changes { | |||
|     private _nextId: number = -1 // Newly assigned ID's are negative
 | ||||
|     private readonly previouslyCreated: OsmObject[] = [] | ||||
|     private readonly _leftRightSensitive: boolean | ||||
|     private readonly _changesetHandler: ChangesetHandler | ||||
|     public readonly _changesetHandler: ChangesetHandler | ||||
|     private readonly _reportError?: (string: string | Error) => void | ||||
| 
 | ||||
|     constructor( | ||||
|  | @ -209,7 +205,7 @@ export class Changes { | |||
|         ].join("\n\n") | ||||
|     } | ||||
| 
 | ||||
|     private static GetNeededIds(changes: ChangeDescription[]) { | ||||
|     public static GetNeededIds(changes: ChangeDescription[]) { | ||||
|         return Utils.Dedup(changes.filter((c) => c.id >= 0).map((c) => c.type + "/" + c.id)) | ||||
|     } | ||||
| 
 | ||||
|  | @ -520,7 +516,7 @@ export class Changes { | |||
|                 const osmObj = await downloader.DownloadObjectAsync(id, 0) | ||||
|                 return { id, osmObj } | ||||
|             } catch (e) { | ||||
|                 const msg = "Could not download OSM-object" + | ||||
|                 const msg = "Could not download OSM-object " + | ||||
|                     id + | ||||
|                     " trying again before dropping it from the changes (" + | ||||
|                     e + | ||||
|  | @ -530,7 +526,7 @@ export class Changes { | |||
|                 return { id, osmObj } | ||||
|             } | ||||
|         } catch (e) { | ||||
|             const msg = "Could not download OSM-object" + | ||||
|             const msg = "Could not download OSM-object " + | ||||
|                 id + | ||||
|                 " dropping it from the changes (" + | ||||
|                 e + | ||||
|  |  | |||
|  | @ -25,7 +25,7 @@ export class ChangesetHandler { | |||
|      * Contains previously rewritten IDs | ||||
|      * @private | ||||
|      */ | ||||
|     private readonly _remappings = new Map<string, string>() | ||||
|     public readonly _remappings = new Map<string, string>() | ||||
|     private readonly _reportError: (e: string | Error) => void | ||||
| 
 | ||||
|     constructor( | ||||
|  | @ -187,7 +187,7 @@ export class ChangesetHandler { | |||
|                 await this.UpdateTags(csId, rewrittenTags) | ||||
|             } catch (e) { | ||||
|                 if (this._reportError) { | ||||
|                     this._reportError("Could not reuse changeset, might be closed: "  + e.stacktrace ?? "" + e) | ||||
|                     this._reportError("Could not reuse changeset "+csId+", might be closed: "  + (e.stacktrace ?? ("" + e))) | ||||
|                 } | ||||
|                 console.warn("Could not upload, changeset is probably closed: ", e) | ||||
|                 openChangeset.setData(undefined) | ||||
|  |  | |||
|  | @ -900,6 +900,8 @@ export default class ThemeViewState implements SpecialVisualizationState { | |||
|                 username: this.osmConnection.userDetails.data?.name, | ||||
|                 userid: this.osmConnection.userDetails.data?.uid, | ||||
|                 pendingChanges: this.changes.pendingChanges.data, | ||||
|                 previousChanges: this.changes.allChanges.data, | ||||
|                 changeRewrites: Utils.MapToObj(this.changes._changesetHandler._remappings) | ||||
|             }), | ||||
|         }) | ||||
|     } | ||||
|  |  | |||
|  | @ -1267,13 +1267,21 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be | |||
|         return track[str2.length][str1.length] | ||||
|     } | ||||
| 
 | ||||
|     public static MapToObj<V>( | ||||
|         d: Map<string, V> | ||||
|     ): Record<string, V>; | ||||
|     public static MapToObj<V, T>( | ||||
|         d: Map<string, V>, | ||||
|         onValue: (t: V, key: string) => T | ||||
|     ): Record<string, T> | ||||
|     public static MapToObj<V, T>( | ||||
|         d: Map<string, V>, | ||||
|         onValue: (t: V, key: string) => T = undefined | ||||
|     ): Record<string, T> { | ||||
|         const o = {} | ||||
|         const keys = Array.from(d.keys()) | ||||
|         keys.sort() | ||||
|         onValue ??= (v => <any> v) | ||||
|         for (const key of keys) { | ||||
|             o[key] = onValue(d.get(key), key) | ||||
|         } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue